I am trying to build a CMake function that builds cuda fatbins files with the included path of all dependent libraries. Those Libs are created for ease of use as an interface only.
The problem is how to extract the recursive included path of all dependencies before execute the custom command I get an error.
I tried some examples but the result is:
-- print_all_include_directories lib DummyCompile_cuda_INPUT_fatbin_offline.cu
-- print_all_include_directories_internal Include directories for target DummyCompile_cuda_INPUT_fatbin_offline.cu:
INCLUDE_DIRS INCLUDE_DIRS-NOTFOUND
-- print_all_include_directories_internal Include directories for target ParamL:
INCLUDE_DIRS INCLUDE_DIRS-NOTFOUND
Instead of printing the dependency path of the libraries which is /…/AnotherFolder.
Maybe there is another way to build fatbin with all included folders
The Main CmMke script is:
cmake_minimum_required(VERSION 3.29)
project(TestJitLto CUDA)
set(CMAKE_CUDA_ARCHITECTURES 86 75 70 )
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CUDA_STANDARD 17)
find_package(CUDAToolkit REQUIRED cusparse cublas cudadevrt cudart nvJitLink)
add_executable(TestJitLto online.cu)
set_target_properties(TestJitLto PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(TestJitLto PUBLIC CUDA::nvJitLink CUDA::cudart CUDA::nvrtc)
ADD_SUBDIRECTORY(AnotherFolder)
ADD_SUBDIRECTORY(JitLtoLib)
Fatbinf generator cmake:
##Function to recursively get and print include directories of all linked libraries
function(print_all_include_directories_internal target)
message(STATUS "print_all_include_directories_internal Include directories for target ${target}:")
# Get the include directories of the target itself
get_target_property(INCLUDE_DIRS ${target} INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(INCLUDE_DIRS ${target} INCLUDE_DIRECTORIES)
message("INCLUDE_DIRS ${INCLUDE_DIRS}")
if (INCLUDE_DIRS)
foreach (dir ${INCLUDE_DIRS})
list(APPEND INCLUDE_LIST_TMP ${dir})
endforeach ()
list(APPEND INCLUDE_LIST_TMP ${INCLUDE_LIST})
list(REMOVE_DUPLICATES INCLUDE_LIST_TMP)
message("INCLUDE_LIST_TMP ${INCLUDE_LIST_TMP}")
set(INCLUDE_LIST2 ${INCLUDE_LIST_TMP})
else ()
set(INCLUDE_LIST2 "")
endif ()
# Now get the libraries linked to this target
get_target_property(LINK_LIBS ${target} LINK_LIBRARIES)
#get_target_property(LINK_LIBS2 ${target} INTERFACE_LINK_LIBRARIES)
set(LINK_LIBS ${LINK_LIBS} ${LINK_LIBS2})
list(REMOVE_DUPLICATES LINK_LIBS)
#message("LINK_LIBS ${LINK_LIBS}")
if (LINK_LIBS)
foreach (linked_lib ${LINK_LIBS})
# Check if the linked library is a target, skip if it's a system library or non-target
if (TARGET ${linked_lib})
#message(STATUS "Checking include directories for linked library: ${linked_lib} ${INCLUDE_LIST}")
print_all_include_directories_internal(${linked_lib}) # Recursive call
list(APPEND INCLUDE_LIST2 ${INCLUDE_LIST})
list(REMOVE_DUPLICATES INCLUDE_LIST2)
else ()
list(APPEND INCLUDE_LIST2 ${INCLUDE_LIST})
list(REMOVE_DUPLICATES INCLUDE_LIST2)
# message(STATUS "INCLUDE_LIST1:" ${INCLUDE_LIST2})
endif ()
endforeach ()
else ()
list(APPEND INCLUDE_LIST2 ${INCLUDE_LIST})
list(REMOVE_DUPLICATES INCLUDE_LIST2)
#message(STATUS "INCLUDE_LIST2:" ${INCLUDE_LIST2})
endif ()
set(INCLUDE_LIST ${INCLUDE_LIST2} PARENT_SCOPE)
endfunction()
function(print_all_include_directories lib)
message(STATUS " print_all_include_directories lib ${lib}")
print_all_include_directories_internal(${lib})
set(INCLUDE_LIST ${INCLUDE_LIST} PARENT_SCOPE)
message(STATUS " print_all_include_directories1 ${INCLUDE_LIST}")
endfunction()
# Function to compile a single CUDA file into a fatbin
function(compile_cuda_fatbin_function INPUT_FILE OUTPUT_DIR DEPENDS_LIBS)
ADD_LIBRARY(DummyCompile_cuda_INPUT_fatbin_${INPUT_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_FILE})
target_link_libraries(DummyCompile_cuda_INPUT_fatbin_${INPUT_FILE} PUBLIC ${DEPENDS_LIBS})
print_all_include_directories(DummyCompile_cuda_INPUT_fatbin_${INPUT_FILE})
get_filename_component(OUT_FILE ${INPUT_FILE} NAME_WLE)
message("CMAKE_CUDA_ARCHITECTURES ${CMAKE_CUDA_ARCHITECTURES}")
# Initialize an empty list for the flags
set(GENCODE_FLAGS "")
# Split the architecture string by semicolons and iterate over each
foreach (ARCH IN LISTS CMAKE_CUDA_ARCHITECTURES)
# Add `-gencode` flags to the list
list(APPEND GENCODE_FLAGS "-gencode arch=compute_${ARCH},code=lto_${ARCH}")
endforeach ()
string(REPLACE ";" " " GENCODE_FLAGS "${GENCODE_FLAGS}")
# Print the generated flags for verification
message(STATUS "Generated -gencode flags1: ${GENCODE_FLAGS}")
message("ARCH_VECTOR is ${GENCODE_FLAGS}")
separate_arguments(GENCODE_FLAGSA UNIX_COMMAND "${GENCODE_FLAGS}")
# Custom command to compile the CUDA file into a fatbin
add_custom_command(
OUTPUT "${OUTPUT_DIR}/${INPUT_FILE}.fatbin"
VERBATIM
COMMAND /usr/local/cuda/bin/nvcc
ARGS ${GENCODE_FLAGSA} -rdc=true -fatbin ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_FILE} -o ${CMAKE_CURRENT_BINARY_DIR}/${OUT_FILE}.fatbin
MAIN_DEPENDENCY "${INPUT_FILE}"
COMMENT "Compiling CUDA binary for ${INPUT_FILE} to fatbin with LTO archive"
)
# Custom target that depends on the fatbin output
add_custom_target(compile_cuda_fatbin_${INPUT_FILE}
DEPENDS "${OUTPUT_DIR}/${INPUT_FILE}.fatbin" ${DEPENDS_LIBS}
)
ADD_LIBRARY(Dummycompile_cuda_fatbin_${INPUT_FILE} INTERFACE)
target_link_libraries(Dummycompile_cuda_fatbin_${INPUT_FILE} INTERFACE ${DEPENDS_LIBS})
target_include_directories(Dummycompile_cuda_fatbin_${INPUT_FILE} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
add_dependencies(Dummycompile_cuda_fatbin_${INPUT_FILE} compile_cuda_fatbin_${INPUT_FILE})
endfunction()
# Function to compile a list of CUDA files into fatbins
function(compile_cuda_fatbin_files_function FILES)
foreach (FILE ${FILES})
compile_cuda_fatbin_function("${FILE}" "${OUTPUT_DIR}" "${LTO_ARC}")
endforeach ()
endfunction()
compile_cuda_fatbin_function(offline.cu ${CMAKE_CURRENT_SOURCE_DIR} ParamL)
Another cmake:
add_library(ParamL INTERFACE)
target_include_directories(ParamL INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
What Am I doing wrong?