Skip to content

Commit d51d2b5

Browse files
committed
[libc] Support add_object_library for the GPU build
This patch unifies the handling of generating the GPU build targets between the `add_entrypoint_library` and the `add_object_library` functions. The `_build_gpu_objects` function will create two targets. One contains a single object file with several GPU binaries embedded in it, a so-called fatbinary. The other is a direct compile of the supported target to be used internally only. This patch pulls out some of the properties logic so that we can handle both more easily. This patch also required adding an ovverride `NO_GPU_BUILD` for cases when we only want to build the source file as normal. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D144214
1 parent 287267c commit d51d2b5

File tree

3 files changed

+90
-66
lines changed

3 files changed

+90
-66
lines changed

libc/cmake/modules/LLVMLibCObjectRules.cmake

Lines changed: 88 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,23 @@ function(_get_common_compile_options output_var flags)
5959
set(${output_var} ${compile_options} PARENT_SCOPE)
6060
endfunction()
6161

62-
# Builds the entrypoint target for the GPU.
62+
# Builds the object target for the GPU.
63+
# This compiles the target for all supported architectures and embeds it into
64+
# host binary for installing. The internal target contains the GPU code directly
65+
# compiled for a single architecture used internally.
6366
# Usage:
64-
# _build_gpu_entrypoint_objects(
67+
# _build_gpu_objects(
6568
# <target_name>
69+
# <internal_target_name>
6670
# SRCS <list of .cpp files>
6771
# HDRS <list of .h files>
6872
# DEPENDS <list of dependencies>
6973
# COMPILE_OPTIONS <optional list of special compile options for this target>
7074
# FLAGS <optional list of flags>
7175
# )
72-
function(_build_gpu_entrypoint_objects fq_target_name)
76+
function(_build_gpu_objects fq_target_name internal_target_name)
7377
cmake_parse_arguments(
74-
"ADD_GPU_ENTRYPOINT_OBJ"
78+
"ADD_GPU_OBJ"
7579
"" # No optional arguments
7680
"NAME;CXX_STANDARD" # Single value arguments
7781
"SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;FLAGS" # Multi value arguments
@@ -82,7 +86,7 @@ function(_build_gpu_entrypoint_objects fq_target_name)
8286
# this so we can support multiple accelerators on the same machine.
8387
foreach(gpu_arch ${all_gpu_architectures})
8488
set(gpu_target_name ${fq_target_name}.${gpu_arch})
85-
set(compile_options ${ADD_GPU_ENTRYPOINT_OBJ_COMPILE_OPTIONS})
89+
set(compile_options ${ADD_GPU_OBJ_COMPILE_OPTIONS})
8690
# Derive the triple from the specified architecture.
8791
if("${gpu_arch}" IN_LIST all_amdgpu_architectures)
8892
set(gpu_target_triple "amdgcn-amd-amdhsa")
@@ -101,14 +105,16 @@ function(_build_gpu_entrypoint_objects fq_target_name)
101105
add_library(${gpu_target_name}
102106
EXCLUDE_FROM_ALL
103107
OBJECT
104-
${ADD_GPU_ENTRYPOINT_OBJ_SRCS}
105-
${ADD_GPU_ENTRYPOINT_OBJ_HDRS}
108+
${ADD_GPU_OBJ_SRCS}
109+
${ADD_GPU_OBJ_HDRS}
106110
)
107111

108112
target_compile_options(${gpu_target_name} PRIVATE ${compile_options})
109113
target_include_directories(${gpu_target_name} PRIVATE ${include_dirs})
110-
add_dependencies(${gpu_target_name} ${ADD_GPU_ENTRYPOINT_OBJ_DEPENDS})
111114
target_compile_definitions(${gpu_target_name} PRIVATE LIBC_COPT_PUBLIC_PACKAGING)
115+
if(ADD_GPU_OBJ_DEPENDS)
116+
add_dependencies(${gpu_target_name} ${ADD_GPU_OBJ_DEPENDS})
117+
endif()
112118

113119
# Append this target to a list of images to package into a single binary.
114120
set(input_file $<TARGET_OBJECTS:${gpu_target_name}>)
@@ -135,7 +141,7 @@ function(_build_gpu_entrypoint_objects fq_target_name)
135141
# TODO: In the future we will want to combine every architecture for a target
136142
# into a single bitcode file and use that. For now we simply build for
137143
# every single one and let the offloading linker handle it.
138-
get_filename_component(stub_filename ${ADD_GPU_ENTRYPOINT_OBJ_SRCS} NAME)
144+
get_filename_component(stub_filename ${ADD_GPU_OBJ_SRCS} NAME)
139145
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs)
140146
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/stubs/${stub_filename} "// Empty file.\n")
141147
add_library(
@@ -151,28 +157,16 @@ function(_build_gpu_entrypoint_objects fq_target_name)
151157
target_include_directories(${fq_target_name} PRIVATE ${include_dirs})
152158
add_dependencies(${fq_target_name} ${full_deps_list} ${packaged_target_name})
153159

154-
set_target_properties(
155-
${fq_target_name}
156-
PROPERTIES
157-
ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}
158-
TARGET_TYPE ${ENTRYPOINT_OBJ_TARGET_TYPE}
159-
OBJECT_FILE "$<TARGET_OBJECTS:${fq_target_name}>"
160-
CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
161-
DEPS "${fq_deps_list}"
162-
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
163-
)
164-
165160
# We only build the internal target for a single supported architecture.
166-
set(internal_target_name ${fq_target_name}.__internal__)
167161
set(include_dirs ${LIBC_BUILD_DIR}/include ${LIBC_SOURCE_DIR} ${LIBC_BUILD_DIR})
168162
if(LIBC_GPU_TARGET_ARCHITECTURE_IS_AMDGPU OR
169163
LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
170164
add_library(
171165
${internal_target_name}
172166
EXCLUDE_FROM_ALL
173167
OBJECT
174-
${ADD_ENTRYPOINT_OBJ_SRCS}
175-
${ADD_ENTRYPOINT_OBJ_HDRS}
168+
${ADD_GPU_OBJ_SRCS}
169+
${ADD_GPU_OBJ_HDRS}
176170
)
177171
target_compile_options(${internal_target_name} BEFORE PRIVATE
178172
${common_compile_options} --target=${LIBC_GPU_TARGET_TRIPLE})
@@ -182,17 +176,9 @@ function(_build_gpu_entrypoint_objects fq_target_name)
182176
target_compile_options(${internal_target_name} PRIVATE -march=${LIBC_GPU_TARGET_ARCHITECTURE})
183177
endif()
184178
target_include_directories(${internal_target_name} PRIVATE ${include_dirs})
185-
add_dependencies(${internal_target_name} ${full_deps_list})
186-
set_target_properties(
187-
${internal_target_name}
188-
PROPERTIES
189-
CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
190-
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
191-
)
192-
set_target_properties(
193-
${fq_target_name}
194-
PROPERTIES OBJECT_FILE_RAW "$<TARGET_OBJECTS:${internal_target_name}>"
195-
)
179+
if(full_deps_list)
180+
add_dependencies(${internal_target_name} ${full_deps_list})
181+
endif()
196182
endif()
197183
endfunction()
198184

@@ -209,7 +195,7 @@ endfunction()
209195
function(create_object_library fq_target_name)
210196
cmake_parse_arguments(
211197
"ADD_OBJECT"
212-
"" # No optional arguments
198+
"NO_GPU_BUNDLE" # No optional arguments
213199
"CXX_STANDARD" # Single value arguments
214200
"SRCS;HDRS;COMPILE_OPTIONS;DEPENDS;FLAGS" # Multivalue arguments
215201
${ARGN}
@@ -219,28 +205,49 @@ function(create_object_library fq_target_name)
219205
message(FATAL_ERROR "'add_object_library' rule requires SRCS to be specified.")
220206
endif()
221207

222-
add_library(
223-
${fq_target_name}
224-
EXCLUDE_FROM_ALL
225-
OBJECT
226-
${ADD_OBJECT_SRCS}
227-
${ADD_OBJECT_HDRS}
228-
)
229-
target_include_directories(
230-
${fq_target_name}
231-
PRIVATE
232-
${LIBC_BUILD_DIR}/include
233-
${LIBC_SOURCE_DIR}
234-
${LIBC_BUILD_DIR}
235-
)
208+
# The GPU build uses a separate internal file.
209+
if(LIBC_TARGET_ARCHITECTURE_IS_GPU AND NOT ${ADD_OBJECT_NO_GPU_BUNDLE})
210+
set(internal_target_name ${fq_target_name}.__internal__)
211+
else()
212+
set(internal_target_name ${fq_target_name})
213+
endif()
214+
215+
get_fq_deps_list(fq_deps_list ${ADD_OBJECT_DEPENDS})
236216
_get_common_compile_options(
237217
compile_options
238218
"${ADD_OBJECT_FLAGS}"
239219
${ADD_OBJECT_COMPILE_OPTIONS}
240220
)
241-
target_compile_options(${fq_target_name} PRIVATE ${compile_options})
242221

243-
get_fq_deps_list(fq_deps_list ${ADD_OBJECT_DEPENDS})
222+
# GPU builds require special handling for the objects because we want to
223+
# export several different targets at once, e.g. for both Nvidia and AMD.
224+
if(LIBC_TARGET_ARCHITECTURE_IS_GPU AND NOT ${ADD_OBJECT_NO_GPU_BUNDLE})
225+
_build_gpu_objects(
226+
${fq_target_name}
227+
${internal_target_name}
228+
SRCS ${ADD_OBJECT_SRCS}
229+
HDRS ${ADD_OBJECT_HDRS}
230+
DEPENDS ${fq_deps_list}
231+
COMPILE_OPTIONS ${common_compile_options}
232+
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
233+
)
234+
else()
235+
add_library(
236+
${fq_target_name}
237+
EXCLUDE_FROM_ALL
238+
OBJECT
239+
${ADD_OBJECT_SRCS}
240+
${ADD_OBJECT_HDRS}
241+
)
242+
target_include_directories(
243+
${fq_target_name}
244+
PRIVATE
245+
${LIBC_BUILD_DIR}/include
246+
${LIBC_SOURCE_DIR}
247+
${LIBC_BUILD_DIR}
248+
)
249+
target_compile_options(${fq_target_name} PRIVATE ${compile_options})
250+
endif()
244251

245252
if(SHOW_INTERMEDIATE_OBJECTS)
246253
message(STATUS "Adding object library ${fq_target_name}")
@@ -262,11 +269,18 @@ function(create_object_library fq_target_name)
262269
${fq_target_name}
263270
PROPERTIES
264271
TARGET_TYPE ${OBJECT_LIBRARY_TARGET_TYPE}
265-
OBJECT_FILES "$<TARGET_OBJECTS:${fq_target_name}>"
266272
CXX_STANDARD ${ADD_OBJECT_CXX_STANDARD}
267273
DEPS "${fq_deps_list}"
268274
FLAGS "${ADD_OBJECT_FLAGS}"
269275
)
276+
277+
if(TARGET ${internal_target_name})
278+
set_target_properties(
279+
${fq_target_name}
280+
PROPERTIES
281+
OBJECT_FILES "$<TARGET_OBJECTS:${internal_target_name}>"
282+
)
283+
endif()
270284
endfunction(create_object_library)
271285

272286
# Internal function, used by `add_object_library`.
@@ -483,13 +497,13 @@ function(create_entrypoint_object fq_target_name)
483497
# GPU builds require special handling for the objects because we want to
484498
# export several different targets at once, e.g. for both Nvidia and AMD.
485499
if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
486-
_build_gpu_entrypoint_objects(
500+
_build_gpu_objects(
487501
${fq_target_name}
502+
${internal_target_name}
488503
SRCS ${ADD_ENTRYPOINT_OBJ_SRCS}
489504
HDRS ${ADD_ENTRYPOINT_OBJ_HDRS}
490505
COMPILE_OPTIONS ${common_compile_options}
491506
DEPENDS ${full_deps_list}
492-
CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
493507
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
494508
)
495509
else()
@@ -505,12 +519,6 @@ function(create_entrypoint_object fq_target_name)
505519
target_compile_options(${internal_target_name} BEFORE PRIVATE ${common_compile_options})
506520
target_include_directories(${internal_target_name} PRIVATE ${include_dirs})
507521
add_dependencies(${internal_target_name} ${full_deps_list})
508-
set_target_properties(
509-
${internal_target_name}
510-
PROPERTIES
511-
CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
512-
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
513-
)
514522

515523
add_library(
516524
${fq_target_name}
@@ -524,22 +532,36 @@ function(create_entrypoint_object fq_target_name)
524532
target_compile_options(${fq_target_name} BEFORE PRIVATE ${common_compile_options} -DLIBC_COPT_PUBLIC_PACKAGING)
525533
target_include_directories(${fq_target_name} PRIVATE ${include_dirs})
526534
add_dependencies(${fq_target_name} ${full_deps_list})
535+
endif()
536+
537+
set_target_properties(
538+
${fq_target_name}
539+
PROPERTIES
540+
ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}
541+
TARGET_TYPE ${ENTRYPOINT_OBJ_TARGET_TYPE}
542+
OBJECT_FILE "$<TARGET_OBJECTS:${fq_target_name}>"
543+
CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
544+
DEPS "${fq_deps_list}"
545+
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
546+
)
527547

548+
if(TARGET ${internal_target_name})
549+
set_target_properties(
550+
${internal_target_name}
551+
PROPERTIES
552+
CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
553+
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
554+
)
528555
set_target_properties(
529556
${fq_target_name}
530557
PROPERTIES
531-
ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}
532-
TARGET_TYPE ${ENTRYPOINT_OBJ_TARGET_TYPE}
533-
OBJECT_FILE "$<TARGET_OBJECTS:${fq_target_name}>"
534558
# TODO: We don't need to list internal object files if the internal
535559
# target is a normal static library.
536560
OBJECT_FILE_RAW "$<TARGET_OBJECTS:${internal_target_name}>"
537-
CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
538-
DEPS "${fq_deps_list}"
539-
FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
540561
)
541562
endif()
542563

564+
543565
if(LLVM_LIBC_ENABLE_LINTING AND TARGET ${internal_target_name})
544566
if(NOT LLVM_LIBC_CLANG_TIDY)
545567
message(FATAL_ERROR "Something is wrong! LLVM_LIBC_ENABLE_LINTING is "

libc/startup/gpu/amdgpu/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_startup_object(
1010
-mcpu=${LIBC_GPU_TARGET_ARCHITECTURE}
1111
-emit-llvm # AMDGPU's intermediate object file format is bitcode.
1212
--target=${LIBC_GPU_TARGET_TRIPLE}
13+
NO_GPU_BUNDLE # Compile this file directly without special GPU handling.
1314
)
1415
get_fq_target_name(crt1 fq_name)
1516

libc/startup/gpu/nvptx/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_startup_object(
1010
-x cuda # Use the CUDA toolchain to emit the `_start` kernel.
1111
--offload-device-only
1212
--offload-arch=${LIBC_GPU_TARGET_ARCHITECTURE}
13+
NO_GPU_BUNDLE # Compile this file directly without special GPU handling.
1314
)
1415
get_fq_target_name(crt1 fq_name)
1516

0 commit comments

Comments
 (0)