2 # A rule for self contained header file targets.
3 # This rule merely copies the header file from the current source directory to
4 # the current binary directory.
10 function(add_header target_name)
11 cmake_parse_arguments(
13 "" # No optional arguments
14 "HDR" # Single value arguments
15 "DEPENDS" # No multi value arguments
18 if(NOT ADD_HEADER_HDR)
19 message(FATAL_ERROR "'add_header' rules requires the HDR argument specifying a headef file.")
22 set(dest_file ${CMAKE_CURRENT_BINARY_DIR}/${ADD_HEADER_HDR})
23 set(src_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_HEADER_HDR})
27 COMMAND cp ${src_file} ${dest_file}
36 if(ADD_HEADER_DEPENDS)
38 ${target_name} ${ADD_HEADER_DEPENDS}
41 endfunction(add_header)
43 # A rule for generated header file targets.
47 # DEF_FILE <.h.def file>
48 # GEN_HDR <generated header file name>
49 # PARAMS <list of name=value pairs>
50 # DATA_FILES <list input data files>
52 function(add_gen_header target_name)
53 cmake_parse_arguments(
55 "" # No optional arguments
56 "DEF_FILE;GEN_HDR" # Single value arguments
57 "PARAMS;DATA_FILES;DEPENDS" # Multi value arguments
60 if(NOT ADD_GEN_HDR_DEF_FILE)
61 message(FATAL_ERROR "`add_gen_hdr` rule requires DEF_FILE to be specified.")
63 if(NOT ADD_GEN_HDR_GEN_HDR)
64 message(FATAL_ERROR "`add_gen_hdr` rule requires GEN_HDR to be specified.")
67 set(out_file ${CMAKE_CURRENT_BINARY_DIR}/${ADD_GEN_HDR_GEN_HDR})
68 set(in_file ${CMAKE_CURRENT_SOURCE_DIR}/${ADD_GEN_HDR_DEF_FILE})
71 if(ADD_GEN_HDR_DATA_FILES)
72 foreach(data_file IN LISTS ADD_GEN_HDR_DATA_FILES)
73 list(APPEND fq_data_files "${CMAKE_CURRENT_SOURCE_DIR}/${data_file}")
77 set(replacement_params "")
78 if(ADD_GEN_HDR_PARAMS)
79 list(APPEND replacement_params "--args" ${ADD_GEN_HDR_PARAMS})
82 set(gen_hdr_script "${LIBC_BUILD_SCRIPTS_DIR}/gen_hdr.py")
86 COMMAND $<TARGET_FILE:libc-hdrgen> -o ${out_file} --header ${ADD_GEN_HDR_GEN_HDR} --def ${in_file} ${replacement_params} -I ${LIBC_SOURCE_DIR} ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
87 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
88 DEPENDS ${in_file} ${fq_data_files} ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td libc-hdrgen
93 DEPENDS ${out_file} ${ADD_GEN_HDR_DEPENDS}
95 endfunction(add_gen_header)
97 set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
99 # A rule for entrypoint object targets.
101 # add_entrypoint_object(
103 # [REDIRECTED] # Specified if the entrypoint is redirected.
104 # SRCS <list of .cpp files>
105 # HDRS <list of .h files>
106 # DEPENDS <list of dependencies>
108 function(add_entrypoint_object target_name)
109 cmake_parse_arguments(
111 "REDIRECTED" # Optional argument
112 "" # No single value arguments
113 "SRCS;HDRS;DEPENDS" # Multi value arguments
116 if(NOT ADD_ENTRYPOINT_OBJ_SRCS)
117 message(FATAL_ERROR "`add_entrypoint_object` rule requires SRCS to be specified.")
119 if(NOT ADD_ENTRYPOINT_OBJ_HDRS)
120 message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.")
124 "${target_name}_objects"
125 # We want an object library as the objects will eventually get packaged into
126 # an archive (like libc.a).
128 ${ADD_ENTRYPOINT_OBJ_SRCS}
129 ${ADD_ENTRYPOINT_OBJ_HDRS}
131 target_compile_options(
132 ${target_name}_objects
135 -fpie ${LLVM_CXX_STD_default}
137 target_include_directories(
138 ${target_name}_objects
140 "${LIBC_BUILD_DIR}/include;${LIBC_SOURCE_DIR};${LIBC_BUILD_DIR}"
143 ${target_name}_objects
146 if(ADD_ENTRYPOINT_OBJ_DEPENDS)
148 ${target_name}_objects
149 ${ADD_ENTRYPOINT_OBJ_DEPENDS}
153 set(object_file_raw "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_raw.o")
154 set(object_file "${CMAKE_CURRENT_BINARY_DIR}/${target_name}.o")
157 OUTPUT ${object_file_raw}
158 DEPENDS $<TARGET_OBJECTS:${target_name}_objects>
159 COMMAND ${CMAKE_LINKER} -r $<TARGET_OBJECTS:${target_name}_objects> -o ${object_file_raw}
162 set(alias_attributes "0,function,global")
163 if(ADD_ENTRYPOINT_OBJ_REDIRECTED)
164 set(alias_attributes "${alias_attributes},hidden")
168 OUTPUT ${object_file}
169 # We llvm-objcopy here as GNU-binutils objcopy does not support the 'hidden' flag.
170 DEPENDS ${object_file_raw} ${llvm-objcopy}
171 COMMAND $<TARGET_FILE:llvm-objcopy> --add-symbol "${target_name}=.llvm.libc.entrypoint.${target_name}:${alias_attributes}" ${object_file_raw} ${object_file}
177 DEPENDS ${object_file}
179 set_target_properties(
182 "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
183 "OBJECT_FILE" ${object_file}
184 "OBJECT_FILE_RAW" ${object_file_raw}
186 endfunction(add_entrypoint_object)
188 # A rule to build a library from a collection of entrypoint objects.
190 # add_entrypoint_library(
191 # DEPENDS <list of add_entrypoint_object targets>
193 function(add_entrypoint_library target_name)
194 cmake_parse_arguments(
196 "" # No optional arguments
197 "" # No single value arguments
198 "DEPENDS" # Multi-value arguments
201 if(NOT ENTRYPOINT_LIBRARY_DEPENDS)
202 message(FATAL_ERROR "'add_entrypoint_library' target requires a DEPENDS list of 'add_entrypoint_object' targets.")
206 foreach(dep IN LISTS ENTRYPOINT_LIBRARY_DEPENDS)
207 get_target_property(dep_type ${dep} "TARGET_TYPE")
208 string(COMPARE EQUAL ${dep_type} ${ENTRYPOINT_OBJ_TARGET_TYPE} dep_is_entrypoint)
209 if(NOT dep_is_entrypoint)
210 message(FATAL_ERROR "Dependency '${dep}' of 'add_entrypoint_collection' is not an 'add_entrypoint_object' target.")
212 get_target_property(target_obj_file ${dep} "OBJECT_FILE")
213 list(APPEND obj_list "${target_obj_file}")
216 set(library_file "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${target_name}${CMAKE_STATIC_LIBRARY_SUFFIX}")
218 OUTPUT ${library_file}
219 COMMAND ${CMAKE_AR} -r ${library_file} ${obj_list}
225 DEPENDS ${library_file}
227 endfunction(add_entrypoint_library)
229 # Rule build a redirector object file.
230 function(add_redirector_object target_name)
231 cmake_parse_arguments(
233 "" # No optional arguments
234 "SRC" # The cpp file in which the redirector is defined.
235 "" # No multivalue arguments
238 if(NOT REDIRECTOR_OBJECT_SRC)
239 message(FATAL_ERROR "'add_redirector_object' rule requires SRC option listing one source file.")
245 ${REDIRECTOR_OBJECT_SRC}
247 target_compile_options(
251 endfunction(add_redirector_object)
253 # Rule to build a shared library of redirector objects.
254 function(add_redirector_library target_name)
255 cmake_parse_arguments(
264 foreach(dep IN LISTS REDIRECTOR_LIBRARY_DEPENDS)
265 # TODO: Ensure that each dep is actually a add_redirector_object target.
266 list(APPEND obj_files $<TARGET_OBJECTS:${dep}>)
269 # TODO: Call the linker explicitly instead of calling the compiler driver to
270 # prevent DT_NEEDED on C++ runtime.
276 set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
278 target_link_libraries(
283 set_target_properties(
288 endfunction(add_redirector_library)
290 # Rule to add a libc unittest.
294 # SUITE <name of the suite this test belongs to>
295 # SRCS <list of .cpp files for the test>
296 # HDRS <list of .h files for the test>
297 # DEPENDS <list of dependencies>
299 function(add_libc_unittest target_name)
300 if(NOT LLVM_INCLUDE_TESTS)
304 cmake_parse_arguments(
306 "" # No optional arguments
307 "SUITE" # Single value arguments
308 "SRCS;HDRS;DEPENDS" # Multi-value arguments
311 if(NOT LIBC_UNITTEST_SRCS)
312 message(FATAL_ERROR "'add_libc_unittest' target requires a SRCS list of .cpp files.")
314 if(NOT LIBC_UNITTEST_DEPENDS)
315 message(FATAL_ERROR "'add_libc_unittest' target requires a DEPENDS list of 'add_entrypoint_object' targets.")
319 foreach(dep IN LISTS LIBC_UNITTEST_DEPENDS)
320 get_target_property(dep_type ${dep} "TARGET_TYPE")
322 string(COMPARE EQUAL ${dep_type} ${ENTRYPOINT_OBJ_TARGET_TYPE} dep_is_entrypoint)
323 if(dep_is_entrypoint)
324 get_target_property(obj_file ${dep} "OBJECT_FILE_RAW")
325 list(APPEND library_deps ${obj_file})
329 # TODO: Check if the dep is a normal CMake library target. If yes, then add it
330 # to the list of library_deps.
336 ${LIBC_UNITTEST_SRCS}
337 ${LIBC_UNITTEST_HDRS}
339 target_include_directories(
344 ${LIBC_BUILD_DIR}/include
348 target_link_libraries(${target_name} PRIVATE ${library_deps})
351 set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
355 ${LIBC_UNITTEST_DEPENDS}
358 target_link_libraries(${target_name} PRIVATE LibcUnitTest libc_test_utils)
361 TARGET ${target_name}
363 COMMAND $<TARGET_FILE:${target_name}>
365 if(LIBC_UNITTEST_SUITE)
367 ${LIBC_UNITTEST_SUITE}
371 endfunction(add_libc_unittest)
373 function(add_libc_testsuite suite_name)
374 add_custom_target(${suite_name})
375 add_dependencies(check-libc ${suite_name})
376 endfunction(add_libc_testsuite)
378 # Rule to add a fuzzer test.
382 # SRCS <list of .cpp files for the test>
383 # HDRS <list of .h files for the test>
384 # DEPENDS <list of dependencies>
386 function(add_libc_fuzzer target_name)
387 cmake_parse_arguments(
389 "" # No optional arguments
390 "" # Single value arguments
391 "SRCS;HDRS;DEPENDS" # Multi-value arguments
394 if(NOT LIBC_FUZZER_SRCS)
395 message(FATAL_ERROR "'add_libc_fuzzer' target requires a SRCS list of .cpp files.")
397 if(NOT LIBC_FUZZER_DEPENDS)
398 message(FATAL_ERROR "'add_libc_fuzzer' target requires a DEPENDS list of 'add_entrypoint_object' targets.")
402 foreach(dep IN LISTS LIBC_FUZZER_DEPENDS)
403 get_target_property(dep_type ${dep} "TARGET_TYPE")
405 string(COMPARE EQUAL ${dep_type} ${ENTRYPOINT_OBJ_TARGET_TYPE} dep_is_entrypoint)
406 if(dep_is_entrypoint)
407 get_target_property(obj_file ${dep} "OBJECT_FILE_RAW")
408 list(APPEND library_deps ${obj_file})
412 # TODO: Check if the dep is a normal CMake library target. If yes, then add it
413 # to the list of library_deps.
422 target_include_directories(
427 ${LIBC_BUILD_DIR}/include
431 target_link_libraries(${target_name} PRIVATE ${library_deps})
434 set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
438 ${LIBC_FUZZER_DEPENDS}
440 add_dependencies(libc-fuzzer ${target_name})
441 endfunction(add_libc_fuzzer)
443 # Rule to add header only libraries.
445 # add_header_library(
447 # HDRS <list of .h files part of the library>
448 # DEPENDS <list of dependencies>
450 function(add_header_library target_name)
451 cmake_parse_arguments(
453 "" # No optional arguments
454 "" # No Single value arguments
455 "HDRS;DEPENDS" # Multi-value arguments
459 if(NOT ADD_HEADER_HDRS)
460 message(FATAL_ERROR "'add_header_library' target requires a HDRS list of .h files.")
463 set(FULL_HDR_PATHS "")
464 # TODO: Remove this foreach block when we can switch to the new
465 # version of the CMake policy CMP0076.
466 foreach(hdr IN LISTS ADD_HEADER_HDRS)
467 list(APPEND FULL_HDR_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${hdr})
470 set(interface_target_name "${target_name}_header_library__")
472 add_library(${interface_target_name} INTERFACE)
473 target_sources(${interface_target_name} INTERFACE ${FULL_HDR_PATHS})
474 if(ADD_HEADER_DEPENDS)
475 add_dependencies(${interface_target_name} ${ADD_HEADER_DEPENDS})
478 add_custom_target(${target_name})
479 add_dependencies(${target_name} ${interface_target_name})
480 set_target_properties(
483 "TARGET_TYPE" "HDR_LIBRARY"
485 endfunction(add_header_library)