Why use add_library({tgt} IMPORTED) versus target_link_libraries( -l {.so | .a})?

10,630

You should use add_library(<tgt> [SHARED|STATIC] IMPORTED) whenever you need to set properties such as dependencies, compile definitions, compile flags etc for <tgt>, and/or by extension, any targets that are linking against <tgt>.

Let's say you have two static libraries; libfoobar.a and libraboof.a, where libfoobar.a requires libraboof.a. Let's also say that these libraries contain some features that are enabled by -DSOME_FEATURE.

add_library(raboof STATIC IMPORTED)
set_target_properties(raboof PROPERTIES
    IMPORTED_LOCATION <path-to-libraboof.a>
    INTERFACE_COMPILE_DEFINITIONS "SOME_FEATURE"
)

add_library(foobar STATIC IMPORTED)
set_target_properties(foobar PROPERTIES
    IMPORTED_LOCATION <path-to-libfoobar.a>
    INTERFACE_LINK_LIBRARIES raboof
)

So when you link against libfoobar.a:

add_executable(my_app main.cpp)
target_link_libraries(my_app foobar)

CMake will make sure to link all dependencies in the correct order and will in this case also append -DSOME_FEATURE to the compile flags when you build my_app. Note that since we added libraboof.a as a dependency to libfoobar.a, -DSOME_FEATURE is added to any target that link against libfoobar.a through the transitive property.

If you don't use add_library(<tgt> <SHARED|STATIC> IMPORTED) in a scenario like this, you would have to manage any dependencies and required build options yourself for each target, which is quite error-prone.

This method is also often used in Config-modules for multi-component libraries to manage dependencies between the components.

Share:
10,630
Spencer Duball
Author by

Spencer Duball

Updated on June 04, 2022

Comments

  • Spencer Duball
    Spencer Duball almost 2 years

    What is the purpose of using the statement:

    add_library(<tgt> [SHARED|STATIC] IMPORTED)
    

    From what I have found even if you create an imported library target above you still would need to specify the specific location of the actual .so or .a. This would take at least 3 cmake commands to link to an executable and the compiler still would not automatically search through the common include directories on your OS.

    Example: cmake code to link IMPORTED lib

    From the CMake documentation I understand there are really 3 ways to link a library that is not built as a target in a subproject of your overall application/library.

    CMake target_link_libraries() documentation

    1. Using a CMake package for one of the shipped package scripts.
    2. Using a linker flag:

      target_link_libraries(<tgt> [SHARED|STATIC|...] -lncursesw)
      
    3. Or using the IMPORTED library method (showcased in code at top).

    A major difference when using the second method is that it only takes a single line of code and will search through all of your compiler's predefined include directories on you OS. Could anyone help me understand why the add_library() method is used?


    Additional Realated SO Posts:

    Include directories for IMPORTED libs

    CMake imported library behavior

  • Jayhello
    Jayhello almost 6 years
    I can't understand you answer very clearly, can you give a example with real code?