@@ -83,6 +83,97 @@ function(get_all_object_file_deps result fq_deps_list)
83
83
set (${result} ${all_deps} PARENT_SCOPE)
84
84
endfunction ()
85
85
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
+
86
177
# A rule to build a library from a collection of entrypoint objects and bundle
87
178
# it in a single LLVM-IR bitcode file.
88
179
# Usage:
0 commit comments