c++cmake

Can I create a cmake "pseudo target" that will do compile/link options for me?


In my project, I have a mix of dependencies, some with cmake files that I can nicely use target_link_libraries() (e.g. boost_program_options) with, but some don't (e.g. openssl; I have to compile a custom version for compatibility reasons) and I have to use ExternalProject_Add and for them, and then I need to use a mixture of target_link_libraries(), target_compile_options() and target_link_options(), e.g.:

# This is only for certain libraries.
target_compile_options(my_program
  PUBLIC
  -I${OPENSSL_INSTALL_DIR}/include
)

# This is only for certain libraries.
target_link_options(my_program
  PUBLIC
  -L${OPENSSL_INSTALL_DIR}/lib
)

# This is only for everything, but I have to remember
# whether I add the target name or the actual library
# files.
target_link_libraries(my_program
  PUBLIC
  boost_program_options
  libssl.a libcrypto.a
)

What I'd rather do is replace this with something like:

# Everything in one place.
target_link_libraries(my_program
  PUBLIC
  boost_program_options
  openssl_pseudo_target
)

And elsewhere have openssl_pseudo_target tell cmake the appropriate compile/link options/libraries to use.

Is there any way to do this, or achieve a similar effect?


Solution

  • This is what Interface Libraries are for. They also provide an example similar to what you want to do:

    Another use-case is to employ an entirely target-focussed design for usage requirements:

    add_library(pic_on INTERFACE)
    set_property(TARGET pic_on PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
    add_library(pic_off INTERFACE)
    set_property(TARGET pic_off PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)
    
    add_library(enable_rtti INTERFACE)
    target_compile_options(enable_rtti INTERFACE
      $<$<OR:$<COMPILER_ID:GNU>,$<COMPILER_ID:Clang>>:-rtti>
    )
    
    add_executable(exe1 exe1.cpp)
    target_link_libraries(exe1 pic_on enable_rtti)
    

    This way, the build specification of exe1 is expressed entirely as linked targets, and the complexity of compiler-specific flags is encapsulated in an INTERFACE library target.

    P.S. There is also find_package(OpenSSL) which provides needed targets so you don't need to make your own.