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