@@ -83,6 +83,97 @@ function(get_all_object_file_deps result fq_deps_list)
8383 set (${result} ${all_deps} PARENT_SCOPE)
8484endfunction ()
8585
86+ # A rule to build a library from a collection of entrypoint objects and bundle
87+ # it into a GPU fatbinary. Usage is the same as 'add_entrypoint_library'.
88+ # Usage:
89+ # add_gpu_entrypoint_library(
90+ # DEPENDS <list of add_entrypoint_object targets>
91+ # )
92+ function (add_gpu_entrypoint_library target_name base_target_name)
93+ cmake_parse_arguments (
94+ "ENTRYPOINT_LIBRARY"
95+ "" # No optional arguments
96+ "" # No single value arguments
97+ "DEPENDS" # Multi-value arguments
98+ ${ARGN}
99+ )
100+ if (NOT ENTRYPOINT_LIBRARY_DEPENDS)
101+ message (FATAL_ERROR "'add_entrypoint_library' target requires a DEPENDS list "
102+ "of 'add_entrypoint_object' targets." )
103+ endif ()
104+
105+ get_fq_deps_list(fq_deps_list ${ENTRYPOINT_LIBRARY_DEPENDS} )
106+ get_all_object_file_deps(all_deps "${fq_deps_list} " )
107+
108+ # The GPU 'libc' needs to be exported in a format that can be linked with
109+ # offloading langauges like OpenMP or CUDA. This wraps every GPU object into a
110+ # fat binary and adds them to a static library.
111+ set (objects "" )
112+ foreach (dep IN LISTS all_deps)
113+ set (object $<$<STREQUAL :$<TARGET_NAME_IF_EXISTS:${dep} >,${dep} >:$<TARGET_OBJECTS:${dep} >>)
114+ string (FIND ${dep} "." last_dot_loc REVERSE )
115+ math (EXPR name_loc "${last_dot_loc} + 1" )
116+ string (SUBSTRING ${dep} ${name_loc} -1 name )
117+ if (LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
118+ set (prefix --image=arch=generic,triple=nvptx64-nvidia-cuda,feature=+ptx63)
119+ elseif (LIBC_TARGET_ARCHITECTURE_IS_AMDGPU)
120+ set (prefix --image=arch=generic,triple=amdgcn-amd-amdhsa)
121+ endif ()
122+
123+ # Use the 'clang-offload-packager' to merge these files into a binary blob.
124+ add_custom_command (
125+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR} /binary/${name} .gpubin"
126+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR} /binary
127+ COMMAND ${LIBC_CLANG_OFFLOAD_PACKAGER}
128+ "${prefix} ,file=$<JOIN:${object} ,,file=>" -o
129+ ${CMAKE_CURRENT_BINARY_DIR} /binary/${name} .gpubin
130+ DEPENDS ${dep} ${base_target_name}
131+ COMMENT "Packaging LLVM offloading binary for '${object} '"
132+ )
133+ add_custom_target (${dep} .__gpubin__ DEPENDS ${dep}
134+ "${CMAKE_CURRENT_BINARY_DIR} /binary/${name} .gpubin" )
135+ if (TARGET clang-offload-packager)
136+ add_dependencies (${dep} .__gpubin__ clang-offload-packager)
137+ endif ()
138+
139+ # CMake does not permit setting the name on object files. In order to have
140+ # human readable names we create an empty stub file with the entrypoint
141+ # name. This empty file will then have the created binary blob embedded.
142+ add_custom_command (
143+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR} /stubs/${name} .cpp"
144+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR} /stubs
145+ COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR} /stubs/${name} .cpp
146+ DEPENDS ${dep} ${dep} .__gpubin__ ${base_target_name}
147+ )
148+ add_custom_target (${dep} .__stub__
149+ DEPENDS ${dep} .__gpubin__ "${CMAKE_CURRENT_BINARY_DIR} /stubs/${name} .cpp" )
150+
151+ add_library (${dep} .__fatbin__
152+ EXCLUDE_FROM_ALL OBJECT
153+ "${CMAKE_CURRENT_BINARY_DIR} /stubs/${name} .cpp"
154+ )
155+
156+ # This is always compiled for the LLVM host triple instead of the native GPU
157+ # triple that is used by default in the build.
158+ target_compile_options (${dep} .__fatbin__ BEFORE PRIVATE -nostdlib)
159+ target_compile_options (${dep} .__fatbin__ PRIVATE
160+ --target =${LLVM_HOST_TRIPLE}
161+ "SHELL:-Xclang -fembed-offload-object=${CMAKE_CURRENT_BINARY_DIR} /binary/${name} .gpubin" )
162+ add_dependencies (${dep} .__fatbin__
163+ ${dep} ${dep} .__stub__ ${dep} .__gpubin__ ${base_target_name} )
164+
165+ # Set the list of newly create fat binaries containing embedded device code.
166+ list (APPEND objects $<TARGET_OBJECTS:${dep} .__fatbin__>)
167+ endforeach ()
168+
169+ add_library (
170+ ${target_name}
171+ STATIC
172+ ${objects}
173+ )
174+ set_target_properties (${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${LIBC_LIBRARY_DIR} )
175+ endfunction (add_gpu_entrypoint_library)
176+
86177# A rule to build a library from a collection of entrypoint objects and bundle
87178# it in a single LLVM-IR bitcode file.
88179# Usage:
0 commit comments