1set(OBJECT_LIBRARY_TARGET_TYPE "OBJECT_LIBRARY")
2
3function(_get_common_compile_options output_var flags)
4  list(FIND flags ${FMA_OPT_FLAG} fma)
5  if(${fma} LESS 0)
6    list(FIND flags "${FMA_OPT_FLAG}__ONLY" fma)
7  endif()
8  if((${fma} GREATER -1) AND (LIBC_CPU_FEATURES MATCHES "FMA"))
9    set(ADD_FMA_FLAG TRUE)
10  endif()
11
12  set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN})
13  if(NOT ${LIBC_TARGET_OS} STREQUAL "windows")
14    set(compile_options ${compile_options} -fpie -ffreestanding -fno-builtin)
15  endif()
16  if(LLVM_COMPILER_IS_GCC_COMPATIBLE)
17    list(APPEND compile_options "-fno-exceptions")
18    list(APPEND compile_options "-fno-unwind-tables")
19    list(APPEND compile_options "-fno-asynchronous-unwind-tables")
20    list(APPEND compile_options "-fno-rtti")
21    if(ADD_FMA_FLAG)
22      list(APPEND compile_options "-mfma")
23    endif()
24  elseif(MSVC)
25    list(APPEND compile_options "/EHs-c-")
26    list(APPEND compile_options "/GR-")
27    if(ADD_FMA_FLAG)
28      list(APPEND compile_options "/arch:AVX2")
29    endif()
30  endif()
31  set(${output_var} ${compile_options} PARENT_SCOPE)
32endfunction()
33
34# Rule which is essentially a wrapper over add_library to compile a set of
35# sources to object files.
36# Usage:
37#     add_object_library(
38#       <target_name>
39#       HDRS <list of header files>
40#       SRCS <list of source files>
41#       DEPENDS <list of dependencies>
42#       COMPILE_OPTIONS <optional list of special compile options for this target>
43#       FLAGS <optional list of flags>
44function(create_object_library fq_target_name)
45  cmake_parse_arguments(
46    "ADD_OBJECT"
47    "" # No optional arguments
48    "CXX_STANDARD" # Single value arguments
49    "SRCS;HDRS;COMPILE_OPTIONS;DEPENDS;FLAGS" # Multivalue arguments
50    ${ARGN}
51  )
52
53  if(NOT ADD_OBJECT_SRCS)
54    message(FATAL_ERROR "'add_object_library' rule requires SRCS to be specified.")
55  endif()
56
57  add_library(
58    ${fq_target_name}
59    EXCLUDE_FROM_ALL
60    OBJECT
61    ${ADD_OBJECT_SRCS}
62    ${ADD_OBJECT_HDRS}
63  )
64  target_include_directories(
65    ${fq_target_name}
66    PRIVATE
67      ${LIBC_BUILD_DIR}/include
68      ${LIBC_SOURCE_DIR}
69      ${LIBC_BUILD_DIR}
70  )
71  _get_common_compile_options(
72    compile_options
73    "${ADD_OBJECT_FLAGS}"
74    ${ADD_OBJECT_COMPILE_OPTIONS}
75  )
76  target_compile_options(${fq_target_name} PRIVATE ${compile_options})
77
78  get_fq_deps_list(fq_deps_list ${ADD_OBJECT_DEPENDS})
79
80  if(SHOW_INTERMEDIATE_OBJECTS)
81    message(STATUS "Adding object library ${fq_target_name}")
82    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
83      foreach(dep IN LISTS ADD_OBJECT_DEPENDS)
84        message(STATUS "  ${fq_target_name} depends on ${dep}")
85      endforeach()
86    endif()
87  endif()
88
89  if(fq_deps_list)
90    add_dependencies(${fq_target_name} ${fq_deps_list})
91  endif()
92
93  if(NOT ADD_OBJECT_CXX_STANDARD)
94    set(ADD_OBJECT_CXX_STANDARD ${CMAKE_CXX_STANDARD})
95  endif()
96
97  set_target_properties(
98    ${fq_target_name}
99    PROPERTIES
100      TARGET_TYPE ${OBJECT_LIBRARY_TARGET_TYPE}
101      OBJECT_FILES "$<TARGET_OBJECTS:${fq_target_name}>"
102      CXX_STANDARD ${ADD_OBJECT_CXX_STANDARD}
103      DEPS "${fq_deps_list}"
104      FLAGS "${ADD_OBJECT_FLAGS}"
105  )
106endfunction(create_object_library)
107
108# Internal function, used by `add_object_library`.
109function(expand_flags_for_object_library target_name flags)
110  cmake_parse_arguments(
111    "EXPAND_FLAGS"
112    "IGNORE_MARKER" # Optional arguments
113    "" # Single-value arguments
114    "DEPENDS;FLAGS" # Multi-value arguments
115    ${ARGN}
116  )
117
118  list(LENGTH flags nflags)
119  if(NOT ${nflags})
120    create_object_library(
121      ${target_name}
122      DEPENDS ${EXPAND_FLAGS_DEPENDS}
123      FLAGS ${EXPAND_FLAGS_FLAGS}
124      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
125    )
126    return()
127  endif()
128
129  list(GET flags 0 flag)
130  list(REMOVE_AT flags 0)
131  extract_flag_modifier(${flag} real_flag modifier)
132
133  if(NOT "${modifier}" STREQUAL "NO")
134    expand_flags_for_object_library(
135      ${target_name}
136      "${flags}"
137      DEPENDS "${EXPAND_FLAGS_DEPENDS}" IGNORE_MARKER
138      FLAGS "${EXPAND_FLAGS_FLAGS}" IGNORE_MARKER
139      "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
140    )
141  endif()
142
143  if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")
144    return()
145  endif()
146
147  set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})
148  list(REMOVE_ITEM NEW_FLAGS ${flag})
149  get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})
150
151  # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
152  # `flag__ONLY` do not.
153  if(NOT "${modifier}")
154    set(TARGET_NAME "${target_name}.__NO_${flag}")
155  else()
156    set(TARGET_NAME "${target_name}")
157  endif()
158
159  expand_flags_for_object_library(
160    ${TARGET_NAME}
161    "${flags}"
162    DEPENDS "${NEW_DEPS}" IGNORE_MARKER
163    FLAGS "${NEW_FLAGS}" IGNORE_MARKER
164    "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
165  )
166endfunction(expand_flags_for_object_library)
167
168function(add_object_library target_name)
169  cmake_parse_arguments(
170    "ADD_TO_EXPAND"
171    "" # Optional arguments
172    "" # Single value arguments
173    "DEPENDS;FLAGS" # Multi-value arguments
174    ${ARGN}
175  )
176
177  get_fq_target_name(${target_name} fq_target_name)
178
179  if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))
180    message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")
181  endif()
182
183  get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})
184  get_flags_from_dep_list(deps_flag_list ${fq_deps_list})
185
186  list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})
187  remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)
188  list(SORT flags)
189
190  if(SHOW_INTERMEDIATE_OBJECTS AND flags)
191    message(STATUS "Object library ${fq_target_name} has FLAGS: ${flags}")
192  endif()
193
194  expand_flags_for_object_library(
195    ${fq_target_name}
196    "${flags}"
197    DEPENDS "${fq_deps_list}" IGNORE_MARKER
198    FLAGS "${flags}" IGNORE_MARKER
199    ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
200  )
201endfunction(add_object_library)
202
203set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
204
205# A rule for entrypoint object targets.
206# Usage:
207#     add_entrypoint_object(
208#       <target_name>
209#       [ALIAS|REDIRECTED] # Specified if the entrypoint is redirected or an alias.
210#       [NAME] <the C name of the entrypoint if different from target_name>
211#       SRCS <list of .cpp files>
212#       HDRS <list of .h files>
213#       DEPENDS <list of dependencies>
214#       COMPILE_OPTIONS <optional list of special compile options for this target>
215#       SPECIAL_OBJECTS <optional list of special object targets added by the rule `add_object`>
216#       FLAGS <optional list of flags>
217#     )
218function(create_entrypoint_object fq_target_name)
219  cmake_parse_arguments(
220    "ADD_ENTRYPOINT_OBJ"
221    "ALIAS;REDIRECTED" # Optional argument
222    "NAME;CXX_STANDARD" # Single value arguments
223    "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;FLAGS"  # Multi value arguments
224    ${ARGN}
225  )
226
227  list(FIND TARGET_ENTRYPOINT_NAME_LIST ${ADD_ENTRYPOINT_OBJ_NAME} entrypoint_name_index)
228  if(${entrypoint_name_index} EQUAL -1)
229    add_custom_target(${fq_target_name})
230    set_target_properties(
231      ${fq_target_name}
232      PROPERTIES
233        "ENTRYPOINT_NAME" ${ADD_ENTRYPOINT_OBJ_NAME}
234        "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
235        "OBJECT_FILE" ""
236        "OBJECT_FILE_RAW" ""
237        "DEPS" ""
238        "SKIPPED" "YES"
239    )
240    message(STATUS "Skipping libc entrypoint ${fq_target_name}.")
241    return()
242  endif()
243
244  if(ADD_ENTRYPOINT_OBJ_ALIAS)
245    # Alias targets help one add aliases to other entrypoint object targets.
246    # One can use alias targets setup OS/machine independent entrypoint targets.
247    list(LENGTH ADD_ENTRYPOINT_OBJ_DEPENDS deps_size)
248    if(NOT (${deps_size} EQUAL "1"))
249      message(FATAL_ERROR "An entrypoint alias should have exactly one dependency.")
250    endif()
251    list(GET ADD_ENTRYPOINT_OBJ_DEPENDS 0 dep_target)
252    get_fq_dep_name(fq_dep_name ${dep_target})
253
254    if(SHOW_INTERMEDIATE_OBJECTS)
255      message(STATUS "Adding entrypoint object ${fq_target_name} as an alias of"
256              " ${fq_dep_name}")
257    endif()
258
259    if(NOT TARGET ${fq_dep_name})
260      message(WARNING "Aliasee ${fq_dep_name} for entrypoint alias ${target_name} missing; "
261                      "Target ${target_name} will be ignored.")
262      return()
263    endif()
264
265    get_target_property(obj_type ${fq_dep_name} "TARGET_TYPE")
266    if((NOT obj_type) OR (NOT (${obj_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE})))
267      message(FATAL_ERROR "The aliasee of an entrypoint alias should be an entrypoint.")
268    endif()
269
270    add_custom_target(${fq_target_name})
271    add_dependencies(${fq_target_name} ${fq_dep_name})
272    get_target_property(object_file ${fq_dep_name} "OBJECT_FILE")
273    get_target_property(object_file_raw ${fq_dep_name} "OBJECT_FILE_RAW")
274    set_target_properties(
275      ${fq_target_name}
276      PROPERTIES
277        ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}
278        TARGET_TYPE ${ENTRYPOINT_OBJ_TARGET_TYPE}
279        IS_ALIAS "YES"
280        OBJECT_FILE ""
281        OBJECT_FILE_RAW ""
282        DEPS "${fq_dep_name}"
283        FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
284    )
285    return()
286  endif()
287
288  if(NOT ADD_ENTRYPOINT_OBJ_SRCS)
289    message(FATAL_ERROR "`add_entrypoint_object` rule requires SRCS to be specified.")
290  endif()
291  if(NOT ADD_ENTRYPOINT_OBJ_HDRS)
292    message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.")
293  endif()
294  if(NOT ADD_ENTRYPOINT_OBJ_CXX_STANDARD)
295    set(ADD_ENTRYPOINT_OBJ_CXX_STANDARD ${CMAKE_CXX_STANDARD})
296  endif()
297
298  _get_common_compile_options(
299    common_compile_options
300    "${ADD_ENTRYPOINT_OBJ_FLAGS}"
301    ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS}
302  )
303  set(internal_target_name ${fq_target_name}.__internal__)
304  set(include_dirs ${LIBC_BUILD_DIR}/include ${LIBC_SOURCE_DIR} ${LIBC_BUILD_DIR})
305  get_fq_deps_list(fq_deps_list ${ADD_ENTRYPOINT_OBJ_DEPENDS})
306  set(full_deps_list ${fq_deps_list} libc.src.__support.common)
307
308  if(SHOW_INTERMEDIATE_OBJECTS)
309    message(STATUS "Adding entrypoint object ${fq_target_name}")
310    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
311      foreach(dep IN LISTS ADD_OBJECT_DEPENDS)
312        message(STATUS "  ${fq_target_name} depends on ${dep}")
313      endforeach()
314    endif()
315  endif()
316
317  add_library(
318    ${internal_target_name}
319    # TODO: We don't need an object library for internal consumption.
320    # A future change should switch this to a normal static library.
321    EXCLUDE_FROM_ALL
322    OBJECT
323    ${ADD_ENTRYPOINT_OBJ_SRCS}
324    ${ADD_ENTRYPOINT_OBJ_HDRS}
325  )
326  target_compile_options(${internal_target_name} BEFORE PRIVATE ${common_compile_options})
327  target_include_directories(${internal_target_name} PRIVATE ${include_dirs})
328  add_dependencies(${internal_target_name} ${full_deps_list})
329  set_target_properties(
330    ${internal_target_name}
331    PROPERTIES
332      CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
333      FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
334  )
335
336  add_library(
337    ${fq_target_name}
338    # We want an object library as the objects will eventually get packaged into
339    # an archive (like libc.a).
340    EXCLUDE_FROM_ALL
341    OBJECT
342    ${ADD_ENTRYPOINT_OBJ_SRCS}
343    ${ADD_ENTRYPOINT_OBJ_HDRS}
344  )
345  target_compile_options(${fq_target_name} BEFORE PRIVATE ${common_compile_options} -DLLVM_LIBC_PUBLIC_PACKAGING)
346  target_include_directories(${fq_target_name} PRIVATE ${include_dirs})
347  add_dependencies(${fq_target_name} ${full_deps_list})
348
349  set_target_properties(
350    ${fq_target_name}
351    PROPERTIES
352      ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}
353      TARGET_TYPE ${ENTRYPOINT_OBJ_TARGET_TYPE}
354      OBJECT_FILE "$<TARGET_OBJECTS:${fq_target_name}>"
355      # TODO: We don't need to list internal object files if the internal
356      # target is a normal static library.
357      OBJECT_FILE_RAW "$<TARGET_OBJECTS:${internal_target_name}>"
358      CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
359      DEPS "${fq_deps_list}"
360      FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
361  )
362
363  if(LLVM_LIBC_ENABLE_LINTING)
364    if(NOT LLVM_LIBC_CLANG_TIDY)
365      message(FATAL_ERROR "Something is wrong!  LLVM_LIBC_ENABLE_LINTING is "
366              "ON but LLVM_LIBC_CLANG_TIDY is not set.")
367    endif()
368
369    # We only want a second invocation of clang-tidy to run
370    # restrict-system-libc-headers if the compiler-resource-dir was set in
371    # order to prevent false-positives due to a mismatch between the host
372    # compiler and the compiled clang-tidy.
373    if(COMPILER_RESOURCE_DIR)
374      # We run restrict-system-libc-headers with --system-headers to prevent
375      # transitive inclusion through compler provided headers.
376      set(restrict_system_headers_check_invocation
377        COMMAND ${LLVM_LIBC_CLANG_TIDY} --system-headers
378        --checks="-*,llvmlibc-restrict-system-libc-headers"
379        # We explicitly set the resource dir here to match the
380        # resource dir of the host compiler.
381        "--extra-arg=-resource-dir=${COMPILER_RESOURCE_DIR}"
382        --quiet
383        -p ${PROJECT_BINARY_DIR}
384        ${ADD_ENTRYPOINT_OBJ_SRCS}
385      )
386    else()
387      set(restrict_system_headers_check_invocation
388        COMMAND ${CMAKE_COMMAND} -E echo "Header file check skipped")
389    endif()
390
391    set(lint_timestamp "${CMAKE_CURRENT_BINARY_DIR}/.${target_name}.__lint_timestamp__")
392    add_custom_command(
393      OUTPUT ${lint_timestamp}
394      # --quiet is used to surpress warning statistics from clang-tidy like:
395      #     Suppressed X warnings (X in non-user code).
396      # There seems to be a bug in clang-tidy where by even with --quiet some
397      # messages from clang's own diagnostics engine leak through:
398      #     X warnings generated.
399      # Until this is fixed upstream, we use -fno-caret-diagnostics to surpress
400      # these.
401      COMMAND ${LLVM_LIBC_CLANG_TIDY}
402              "--extra-arg=-fno-caret-diagnostics" --quiet
403              # Path to directory containing compile_commands.json
404              -p ${PROJECT_BINARY_DIR}
405              ${ADD_ENTRYPOINT_OBJ_SRCS}
406      # See above: this might be a second invocation of clang-tidy depending on
407      # the conditions above.
408      ${restrict_system_headers_check_invocation}
409      # We have two options for running commands, add_custom_command and
410      # add_custom_target. We don't want to run the linter unless source files
411      # have changed. add_custom_target explicitly runs everytime therefore we
412      # use add_custom_command. This function requires an output file and since
413      # linting doesn't produce a file, we create a dummy file using a
414      # crossplatform touch.
415      COMMAND "${CMAKE_COMMAND}" -E touch ${lint_timestamp}
416      COMMENT "Linting... ${target_name}"
417      DEPENDS clang-tidy ${internal_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS}
418      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
419    )
420  endif()
421
422endfunction(create_entrypoint_object)
423
424# Internal function, used by `add_entrypoint_object`.
425function(expand_flags_for_entrypoint_object target_name flags)
426  cmake_parse_arguments(
427    "EXPAND_FLAGS"
428    "IGNORE_MARKER" # Optional arguments
429    "" # Single-value arguments
430    "DEPENDS;FLAGS" # Multi-value arguments
431    ${ARGN}
432  )
433
434  list(LENGTH flags nflags)
435  if(NOT ${nflags})
436    create_entrypoint_object(
437      ${target_name}
438      DEPENDS ${EXPAND_FLAGS_DEPENDS}
439      FLAGS ${EXPAND_FLAGS_FLAGS}
440      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
441    )
442    return()
443  endif()
444
445  list(GET flags 0 flag)
446  list(REMOVE_AT flags 0)
447  extract_flag_modifier(${flag} real_flag modifier)
448
449  if(NOT "${modifier}" STREQUAL "NO")
450    expand_flags_for_entrypoint_object(
451      ${target_name}
452      "${flags}"
453      DEPENDS "${EXPAND_FLAGS_DEPENDS}" IGNORE_MARKER
454      FLAGS "${EXPAND_FLAGS_FLAGS}" IGNORE_MARKER
455      "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
456    )
457  endif()
458
459  if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")
460    return()
461  endif()
462
463  set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})
464  list(REMOVE_ITEM NEW_FLAGS ${flag})
465  get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})
466
467  # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
468  # `flag__ONLY` do not.
469  if(NOT "${modifier}")
470    set(TARGET_NAME "${target_name}.__NO_${flag}")
471  else()
472    set(TARGET_NAME "${target_name}")
473  endif()
474
475  expand_flags_for_entrypoint_object(
476    ${TARGET_NAME}
477    "${flags}"
478    DEPENDS "${NEW_DEPS}" IGNORE_MARKER
479    FLAGS "${NEW_FLAGS}" IGNORE_MARKER
480    "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
481  )
482endfunction(expand_flags_for_entrypoint_object)
483
484function(add_entrypoint_object target_name)
485  cmake_parse_arguments(
486    "ADD_TO_EXPAND"
487    "" # Optional arguments
488    "NAME" # Single value arguments
489    "DEPENDS;FLAGS" # Multi-value arguments
490    ${ARGN}
491  )
492
493  get_fq_target_name(${target_name} fq_target_name)
494
495  if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))
496    message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")
497  endif()
498
499  get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})
500  get_flags_from_dep_list(deps_flag_list ${fq_deps_list})
501
502  list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})
503  remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)
504  list(SORT flags)
505
506  if(SHOW_INTERMEDIATE_OBJECTS AND flags)
507    message(STATUS "Object library ${fq_target_name} has FLAGS: ${flags}")
508  endif()
509
510  if(NOT ADD_TO_EXPAND_NAME)
511    set(ADD_TO_EXPAND_NAME ${target_name})
512  endif()
513
514  expand_flags_for_entrypoint_object(
515    ${fq_target_name}
516    "${flags}"
517    NAME ${ADD_TO_EXPAND_NAME} IGNORE_MARKER
518    DEPENDS "${fq_deps_list}" IGNORE_MARKER
519    FLAGS "${flags}" IGNORE_MARKER
520    ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
521  )
522endfunction(add_entrypoint_object)
523
524set(ENTRYPOINT_EXT_TARGET_TYPE "ENTRYPOINT_EXT")
525
526# A rule for external entrypoint targets.
527# Usage:
528#     add_entrypoint_external(
529#       <target_name>
530#       DEPENDS <list of dependencies>
531#     )
532function(add_entrypoint_external target_name)
533  cmake_parse_arguments(
534    "ADD_ENTRYPOINT_EXT"
535    "" # No optional arguments
536    "" # No single value arguments
537    "DEPENDS"  # Multi value arguments
538    ${ARGN}
539  )
540  get_fq_target_name(${target_name} fq_target_name)
541  set(entrypoint_name ${target_name})
542
543  add_custom_target(${fq_target_name})
544  set_target_properties(
545    ${fq_target_name}
546    PROPERTIES
547      "ENTRYPOINT_NAME" ${entrypoint_name}
548      "TARGET_TYPE" ${ENTRYPOINT_EXT_TARGET_TYPE}
549      "DEPS" "${ADD_ENTRYPOINT_EXT_DEPENDS}"
550  )
551
552endfunction(add_entrypoint_external)
553
554# Rule build a redirector object file.
555function(add_redirector_object target_name)
556  cmake_parse_arguments(
557    "REDIRECTOR_OBJECT"
558    "" # No optional arguments
559    "SRC" # The cpp file in which the redirector is defined.
560    "" # No multivalue arguments
561    ${ARGN}
562  )
563  if(NOT REDIRECTOR_OBJECT_SRC)
564    message(FATAL_ERROR "'add_redirector_object' rule requires SRC option listing one source file.")
565  endif()
566
567  add_library(
568    ${target_name}
569    EXCLUDE_FROM_ALL
570    OBJECT
571    ${REDIRECTOR_OBJECT_SRC}
572  )
573  target_compile_options(
574    ${target_name}
575    BEFORE PRIVATE -fPIC ${LIBC_COMPILE_OPTIONS_DEFAULT}
576  )
577endfunction(add_redirector_object)
578