Passing list of libraries to ExternalProject_Add

I need to use two different compilers to build my entire project. This is because part of the project needs OpenMP support, but the primary compilers for some of the platforms do not have good OpenMP support. To do this, I build that part of the project as an ExternalProject – allowing CMake to set up an entirely separate environment. This has worked fine for a while.

My project has become more complex such that now the sub-project needs to link against some libraries from the main project. Consequently, I need to pass those library targets through.

In my main CMake project context, I:

ADD_LIBRARY( foo
foo.cpp
)

ADD_LIBRARY( bar
bar.cpp
)

SET( COMMON_LIBRARIES
    foo
    bar
)

ExternalProject_Add( SUBPROJECT
    #.....
    CMAKE_ARGS -DCMAKE_C_COMPILER=${C_OMP_COMPILER}
        -DCMAKE_CXX_COMPILER=${CXX_OMP_COMPILER}
        -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
        -DCOMMON_LIBRARIES=${COMMON_LIBRARIES}
    INSTALL_COMMAND ""
)

Then, in my SUBPROJECT context, I:

MESSAGE( STATUS "COMMON_LIBRARIES = ${COMMON_LIBRARIES}" )

TARGET_LINK_LIBRARIES( omp_subtarget PUBLIC ${COMMON_LIBRARIES} )

I presently have two problems…

In my SUBPROJECT context, only the first library in the list comes through. I.e. the MESSAGE statement outputs:

COMMON_LIBRARIES = foo

Second, only the library name is passed (not a target), so I either need to pass the full path, or I need to figure out a way to pass a target.

I think I will be able to resolve this with something based on

get_target_property( full_foo_path foo LOCATION)

but bonus points if someone can come up with a nice solution that iterates through the entire list of libraries in COMMON_LIBRARIES, turning them into full absolute paths.

Thanks in advance for any help,

Rob

OK, I’ve written something that seems to loop over my libraries and build up the full paths as I needed…

set( lib_string )
foreach( lib ${COMMON_LIBRARIES} )
    if( TARGET ${lib} )
        get_target_property( libpath ${lib} BINARY_DIR )
        list( APPEND lib_string ${libpath}/${lib} )
    else()
        list( APPEND lib_string ${lib} )
    endif()
endforeach()

However, overall my solution still suffers the original problem that only the first list entry gets passed to the interior context. I have noticed that CMake does give an error…

CMake Warning:
  Ignoring extra path from command line:

   "/path/to/second/lib/bar"

I have figured out that the problem is with the ‘;’ list separator.

Somehow the shell interpreter gets involved and the semicolons are replaced with newlines. I’m on MacOS, but also need solutions that work on Windows and Linux.

I can think of a variety of possible ugly solutions – search and replace the semicolons with some other character. Then, in the interior context, switch them back.

However, this seems cumbersome and possibly challenging to make cross platform (different shells may escape characters differently or interpret characters differently.)

What is the canonical CMake way of handling this?