Detecting if a target has CUDA sources with separable compilation

In the context of this project: GitHub - celeritas-project/CudaRdcUtils: CMake utility functions for building and linking libraries containing CUDA relocatable device code
that help solve the NVidia Relocatable Device Code conundrum.

We need to loop over the sources of a library (to see if any are CUDA sources). We acquire the sources via:

get_target_property(_target_sources library_name SOURCES )

and then loop through them via:

  foreach(_source "${${ARGN}}")
    get_source_file_property(_iscudafile "${_source}" LANGUAGE)
    ...
  endforeach()

and this work nicely in almost of cases.

However some users decided to use this ‘legal’ looking pattern:

add_library(library_name somefile.cxx $<$<BOOL:${_USERPROJECT_ENABLE_CUDA}>:SomeCudaFile.cu;AnotherCudaFile.cu> otherfile.cxx)

And this gets screwed up because the successive values of _source are (one by line):

somefile.cxx
$<$<BOOL:ON
SomeCudaFile.cu
AnotherCudaFile.cu
otherfile.cxx

Instead of having the $<$<BOOL:ON>:SomeCudaFile.cu;AnotherCudaFile.cu> as a second line (out of 3). There is also no way to reconstruct it as the end is not marked as anyway.

Short of demanding the user to change their code, what are the option to handle this situations?
(this is related to CMake challenges with nested list).

Cc: @robert.maynard

Since the list of sources can depend on generator expressions, even CMake itself doesn’t know the answer to that question until generate time. It is not possible to know this information at configure time in general. What do you want to do in response to it?

If the whole generator expression was passed as a single item (instead of N items), at the very least we could ‘skip’ it or probably better I could detect that it is a generator expression and either

  • tell the user that generator expression are not support
  • or even look at its components

Stepping back, is there a better way to answer the question:

  • Is there any CUDA source file in this library
  • and is cuda separatable compilation enabled for the library

Context:
if the condition above are true (and this library needs to be used by any other library), the only solution (that we know of) to properly handle nvcc and nvlink quirks is to replace that single library by 3 libraries files (an object library, a static library and a ‘final’ library). This is because an executable can (in practice due to the nvlink implementation) load one and only one result of nvlink (which was invoked passing the .o (eg. final static libraries) for all the Relocatable Device Code libraries involved in that executable).

You can use string(GENEX_STRIP) to filter out generator expressions before iterating.

In general these questions cannot be answered at configure time unless you ask the project to tell you explicitly through some other method.

You can use string(GENEX_STRIP) to filter out generator expressions before iterating.

Thanks.

In general these questions cannot be answered at configure time unless you ask the project to tell you explicitly through some other method.

This sounds like the conclusion would be that the concept prototyped in GitHub - celeritas-project/CudaRdcUtils: CMake utility functions for building and linking libraries containing CUDA relocatable device code can then only be implemented by CMake proper (i.e. at generation time), isn’t it?

Likely yes.

Is anyone that works in the innards of CMake interest in incorporating the concept and thus add ‘proper’ support nvcc’s relocatable device code? The above mentioned script is used by a couple of projects and is decent starting point.

1 Like

No one is currently working on CMake support for CUDA relocatable device code AFAIK. Please open an issue to propose it, at least to have a common tracking point.

The issue was opened at https://gitlab.kitware.com/cmake/cmake/-/issues/26780