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