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