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(OBJECT_LIBRARY_TARGET_TYPE "OBJECT_LIBRARY")
99 # Rule which is essentially a wrapper over add_library to compile a set of
100 # sources to object files.
102 # add_object_library(
104 # HDRS <list of header files>
105 # SRCS <list of source files>
106 # DEPENDS <list of dependencies>
107 # COMPILE_OPTIONS <optional list of special compile options for this target>
108 function(add_object_library target_name)
109 cmake_parse_arguments(
111 "" # No option arguments
112 "" # Single value arguments
113 "SRCS;HDRS;COMPILE_OPTIONS;DEPENDS" # Multivalue arguments
117 if(NOT ADD_OBJECT_SRCS)
118 message(FATAL_ERROR "'add_object_library' rule requires SRCS to be specified.")
127 target_include_directories(
130 "${LIBC_BUILD_DIR}/include;${LIBC_SOURCE_DIR};${LIBC_BUILD_DIR}"
132 if(ADD_OBJECT_COMPILE_OPTIONS)
133 target_compile_options(
135 PRIVATE ${ADD_OBJECT_COMPILE_OPTIONS}
139 set(all_object_files $<TARGET_OBJECTS:${target_name}>)
140 if(ADD_OBJECT_DEPENDS)
143 ${ADD_OBJECT_DEPENDS}
145 foreach(obj_target IN LISTS ADD_ENTRYPOINT_OBJ_SPECIAL_OBJECTS)
146 get_target_property(obj_type ${obj_target} "TARGET_TYPE")
147 if((NOT obj_type) OR (NOT (${obj_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE})))
150 # If a dependency is also a object file library, we will collect the list of
151 # object files from it.
152 get_target_property(obj_files ${obj_target} "OBJECT_FILES")
153 list(APPEND all_object_files ${obj_files})
154 endforeach(obj_target)
156 list(REMOVE_DUPLICATES all_object_files)
158 set_target_properties(
161 "TARGET_TYPE" ${OBJECT_LIBRARY_TARGET_TYPE}
162 "OBJECT_FILES" "${all_object_files}"
164 endfunction(add_object_library)
166 set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
168 # A rule for entrypoint object targets.
170 # add_entrypoint_object(
172 # [REDIRECTED] # Specified if the entrypoint is redirected.
173 # [NAME] <the C name of the entrypoint if different from target_name>
174 # SRCS <list of .cpp files>
175 # HDRS <list of .h files>
176 # DEPENDS <list of dependencies>
177 # COMPILE_OPTIONS <optional list of special compile options for this target>
178 # SPECIAL_OBJECTS <optional list of special object targets added by the rule `add_object`>
180 function(add_entrypoint_object target_name)
181 cmake_parse_arguments(
183 "REDIRECTED" # Optional argument
184 "NAME" # Single value arguments
185 "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi value arguments
188 if(NOT ADD_ENTRYPOINT_OBJ_SRCS)
189 message(FATAL_ERROR "`add_entrypoint_object` rule requires SRCS to be specified.")
191 if(NOT ADD_ENTRYPOINT_OBJ_HDRS)
192 message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.")
195 set(entrypoint_name ${target_name})
196 if(ADD_ENTRYPOINT_OBJ_NAME)
197 set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME})
201 "${target_name}_objects"
202 # We want an object library as the objects will eventually get packaged into
203 # an archive (like libc.a).
205 ${ADD_ENTRYPOINT_OBJ_SRCS}
206 ${ADD_ENTRYPOINT_OBJ_HDRS}
208 target_compile_options(
209 ${target_name}_objects
212 -fpie ${LLVM_CXX_STD_default}
214 target_include_directories(
215 ${target_name}_objects
217 "${LIBC_BUILD_DIR}/include;${LIBC_SOURCE_DIR};${LIBC_BUILD_DIR}"
220 ${target_name}_objects
224 if(ADD_ENTRYPOINT_OBJ_DEPENDS)
226 ${target_name}_objects
227 ${ADD_ENTRYPOINT_OBJ_DEPENDS}
229 foreach(dep_target IN LISTS ADD_ENTRYPOINT_OBJ_DEPENDS)
230 if(NOT TARGET ${dep_target})
231 # Not all targets will be visible. So, we will ignore those which aren't
235 get_target_property(obj_type ${dep_target} "TARGET_TYPE")
236 if((NOT obj_type) OR (NOT (${obj_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE})))
237 # Even from among the visible targets, we will collect object files
238 # only from add_object_library targets.
241 # Calling get_target_property requires that the target be visible at this
242 # point. For object library dependencies, this is a reasonable requirement.
243 # We can revisit this in future if we need cases which break under this
245 get_target_property(obj_files ${dep_target} "OBJECT_FILES")
246 list(APPEND dep_objects ${obj_files})
247 endforeach(dep_target)
249 list(REMOVE_DUPLICATES dep_objects)
251 if(ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS)
252 target_compile_options(
253 ${target_name}_objects
254 PRIVATE ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS}
258 set(object_file_raw "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_raw.o")
259 set(object_file "${CMAKE_CURRENT_BINARY_DIR}/${target_name}.o")
261 set(input_objects $<TARGET_OBJECTS:${target_name}_objects>)
263 OUTPUT ${object_file_raw}
264 DEPENDS ${input_objects}
265 COMMAND ${CMAKE_LINKER} -r ${input_objects} -o ${object_file_raw}
268 set(alias_attributes "0,function,global")
269 if(ADD_ENTRYPOINT_OBJ_REDIRECTED)
270 set(alias_attributes "${alias_attributes},hidden")
274 OUTPUT ${object_file}
275 # We llvm-objcopy here as GNU-binutils objcopy does not support the 'hidden' flag.
276 DEPENDS ${object_file_raw} ${llvm-objcopy}
277 COMMAND $<TARGET_FILE:llvm-objcopy> --add-symbol "${entrypoint_name}=.llvm.libc.entrypoint.${entrypoint_name}:${alias_attributes}" ${object_file_raw} ${object_file}
283 DEPENDS ${object_file}
285 set(all_objects ${object_file})
286 list(APPEND all_objects ${dep_objects})
287 set(all_objects_raw ${object_file_raw})
288 list(APPEND all_objects_raw ${dep_objects})
289 set_target_properties(
292 "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
293 "OBJECT_FILES" "${all_objects}"
294 "OBJECT_FILES_RAW" "${all_objects_raw}"
296 endfunction(add_entrypoint_object)
298 # A rule to build a library from a collection of entrypoint objects.
300 # add_entrypoint_library(
301 # DEPENDS <list of add_entrypoint_object targets>
303 function(add_entrypoint_library target_name)
304 cmake_parse_arguments(
306 "" # No optional arguments
307 "" # No single value arguments
308 "DEPENDS" # Multi-value arguments
311 if(NOT ENTRYPOINT_LIBRARY_DEPENDS)
312 message(FATAL_ERROR "'add_entrypoint_library' target requires a DEPENDS list of 'add_entrypoint_object' targets.")
316 foreach(dep IN LISTS ENTRYPOINT_LIBRARY_DEPENDS)
317 get_target_property(dep_type ${dep} "TARGET_TYPE")
318 if(NOT (${dep_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}))
319 message(FATAL_ERROR "Dependency '${dep}' of 'add_entrypoint_collection' is not an 'add_entrypoint_object' target.")
321 get_target_property(target_obj_files ${dep} "OBJECT_FILES")
322 list(APPEND obj_list "${target_obj_files}")
324 list(REMOVE_DUPLICATES obj_list)
326 set(library_file "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${target_name}${CMAKE_STATIC_LIBRARY_SUFFIX}")
328 OUTPUT ${library_file}
329 COMMAND ${CMAKE_AR} -r ${library_file} ${obj_list}
335 DEPENDS ${library_file}
337 endfunction(add_entrypoint_library)
339 # Rule build a redirector object file.
340 function(add_redirector_object target_name)
341 cmake_parse_arguments(
343 "" # No optional arguments
344 "SRC" # The cpp file in which the redirector is defined.
345 "" # No multivalue arguments
348 if(NOT REDIRECTOR_OBJECT_SRC)
349 message(FATAL_ERROR "'add_redirector_object' rule requires SRC option listing one source file.")
355 ${REDIRECTOR_OBJECT_SRC}
357 target_compile_options(
361 endfunction(add_redirector_object)
363 # Rule to build a shared library of redirector objects.
364 function(add_redirector_library target_name)
365 cmake_parse_arguments(
374 foreach(dep IN LISTS REDIRECTOR_LIBRARY_DEPENDS)
375 # TODO: Ensure that each dep is actually a add_redirector_object target.
376 list(APPEND obj_files $<TARGET_OBJECTS:${dep}>)
379 # TODO: Call the linker explicitly instead of calling the compiler driver to
380 # prevent DT_NEEDED on C++ runtime.
386 set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
388 target_link_libraries(
393 set_target_properties(
398 endfunction(add_redirector_library)
400 # Rule to add a libc unittest.
404 # SUITE <name of the suite this test belongs to>
405 # SRCS <list of .cpp files for the test>
406 # HDRS <list of .h files for the test>
407 # DEPENDS <list of dependencies>
408 # COMPILE_OPTIONS <list of special compile options for this target>
410 function(add_libc_unittest target_name)
411 if(NOT LLVM_INCLUDE_TESTS)
415 cmake_parse_arguments(
417 "" # No optional arguments
418 "SUITE" # Single value arguments
419 "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi-value arguments
422 if(NOT LIBC_UNITTEST_SRCS)
423 message(FATAL_ERROR "'add_libc_unittest' target requires a SRCS list of .cpp files.")
425 if(NOT LIBC_UNITTEST_DEPENDS)
426 message(FATAL_ERROR "'add_libc_unittest' target requires a DEPENDS list of 'add_entrypoint_object' targets.")
430 foreach(dep IN LISTS LIBC_UNITTEST_DEPENDS)
431 get_target_property(dep_type ${dep} "TARGET_TYPE")
432 if(${dep_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE})
433 get_target_property(obj_files ${dep} "OBJECT_FILES_RAW")
434 list(APPEND library_deps ${obj_files})
435 elseif(${dep_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE})
436 get_target_property(obj_files ${dep} "OBJECT_FILES")
437 list(APPEND library_deps ${obj_files})
439 # TODO: Check if the dep is a normal CMake library target. If yes, then add it
440 # to the list of library_deps.
442 list(REMOVE_DUPLICATES library_deps)
447 ${LIBC_UNITTEST_SRCS}
448 ${LIBC_UNITTEST_HDRS}
450 target_include_directories(
455 ${LIBC_BUILD_DIR}/include
457 if(LIBC_UNITTEST_COMPILE_OPTIONS)
458 target_compile_options(
460 PRIVATE ${LIBC_UNITTEST_COMPILE_OPTIONS}
465 target_link_libraries(${target_name} PRIVATE ${library_deps})
468 set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
472 ${LIBC_UNITTEST_DEPENDS}
475 target_link_libraries(${target_name} PRIVATE LibcUnitTest libc_test_utils)
478 TARGET ${target_name}
480 COMMAND $<TARGET_FILE:${target_name}>
482 if(LIBC_UNITTEST_SUITE)
484 ${LIBC_UNITTEST_SUITE}
488 endfunction(add_libc_unittest)
490 function(add_libc_testsuite suite_name)
491 add_custom_target(${suite_name})
492 add_dependencies(check-libc ${suite_name})
493 endfunction(add_libc_testsuite)
495 # Rule to add a fuzzer test.
499 # SRCS <list of .cpp files for the test>
500 # HDRS <list of .h files for the test>
501 # DEPENDS <list of dependencies>
503 function(add_libc_fuzzer target_name)
504 cmake_parse_arguments(
506 "" # No optional arguments
507 "" # Single value arguments
508 "SRCS;HDRS;DEPENDS" # Multi-value arguments
511 if(NOT LIBC_FUZZER_SRCS)
512 message(FATAL_ERROR "'add_libc_fuzzer' target requires a SRCS list of .cpp files.")
514 if(NOT LIBC_FUZZER_DEPENDS)
515 message(FATAL_ERROR "'add_libc_fuzzer' target requires a DEPENDS list of 'add_entrypoint_object' targets.")
519 foreach(dep IN LISTS LIBC_FUZZER_DEPENDS)
520 get_target_property(dep_type ${dep} "TARGET_TYPE")
522 string(COMPARE EQUAL ${dep_type} ${ENTRYPOINT_OBJ_TARGET_TYPE} dep_is_entrypoint)
523 if(dep_is_entrypoint)
524 get_target_property(obj_file ${dep} "OBJECT_FILES_RAW")
525 list(APPEND library_deps ${obj_file})
529 # TODO: Check if the dep is a normal CMake library target. If yes, then add it
530 # to the list of library_deps.
539 target_include_directories(
544 ${LIBC_BUILD_DIR}/include
548 target_link_libraries(${target_name} PRIVATE ${library_deps})
551 set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
555 ${LIBC_FUZZER_DEPENDS}
557 add_dependencies(libc-fuzzer ${target_name})
558 endfunction(add_libc_fuzzer)
560 # Rule to add header only libraries.
562 # add_header_library(
564 # HDRS <list of .h files part of the library>
565 # DEPENDS <list of dependencies>
567 function(add_header_library target_name)
568 cmake_parse_arguments(
570 "" # No optional arguments
571 "" # No Single value arguments
572 "HDRS;DEPENDS" # Multi-value arguments
576 if(NOT ADD_HEADER_HDRS)
577 message(FATAL_ERROR "'add_header_library' target requires a HDRS list of .h files.")
580 set(FULL_HDR_PATHS "")
581 # TODO: Remove this foreach block when we can switch to the new
582 # version of the CMake policy CMP0076.
583 foreach(hdr IN LISTS ADD_HEADER_HDRS)
584 list(APPEND FULL_HDR_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${hdr})
587 set(interface_target_name "${target_name}_header_library__")
589 add_library(${interface_target_name} INTERFACE)
590 target_sources(${interface_target_name} INTERFACE ${FULL_HDR_PATHS})
591 if(ADD_HEADER_DEPENDS)
592 add_dependencies(${interface_target_name} ${ADD_HEADER_DEPENDS})
595 add_custom_target(${target_name})
596 add_dependencies(${target_name} ${interface_target_name})
597 set_target_properties(
600 "TARGET_TYPE" "HDR_LIBRARY"
602 endfunction(add_header_library)