Generator Expressions and Namespace in target_link_libraries

Yet another post in “Matt tries to learn Effective CMake”. This time, it’s generator expressions!

So, I have a code where we want to link in a library only if an option() is true. So I have (simplified):

target_link_libraries(this PRIVATE MPI::MPI_Fortran)
  target_link_libraries(this PRIVATE FLAP::FLAP)
endif ()

and this works. But then I thought “Maybe I can make this more compact (and much less readable?) with Generator Expressions!” :slight_smile: So I tried:

target_link_libraries(this PRIVATE MPI::MPI_Fortran $<$<BOOL:BUILD_WITH_FLAP>:FLAP::FLAP>)

Now, obviously, if this worked, I wouldn’t be here. When I try this I get:

CMake Error at ESMA_cmake/ecbuild/cmake/ecbuild_add_library.cmake:268 (add_library):
  Target "MAPL.cap" links to target "FLAP::FLAP" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

which is a fancy enough CMake error that I’m not sure what it means.

So, what is the right way to do this? Or should I just stick with the more-readable three-line if-test version?

ETA: Note: We do have in the code:

option(BUILD_WITH_FLAP "Use FLAP for command line processing" ON)
  find_package(FLAP REQUIRED)
endif ()

and I am building with -DBUILD_WITH_FLAP=OFF

This should be:

target_link_libraries(this PRIVATE MPI::MPI_Fortran $<$<BOOL:${BUILD_WITH_FLAP}>:FLAP::FLAP>)

This is because variables don’t “exist” at genex evaluation time, so BUILD_WITH_FLAP is taken as a string for which to determine the boolean-ness of. Since it is not one of CMake’s “false” values, it is “true”.

1 Like

Graaaah! I think I got hit with this in one of my other questions here or on GitHub Actions or something. Thanks, it of course works. Now to ponder if I should stick with easy-to-read-but-verbose, or compact-but-preserves-my-job-because-complicated. :smiley:

For complicated expressions, I recommend building them up using explicit variable names.