brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.1 KiB · 6c534df Raw
510 lines · plain
1set(OBJECT_LIBRARY_TARGET_TYPE "OBJECT_LIBRARY")2set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")3set(ENTRYPOINT_EXT_TARGET_TYPE "ENTRYPOINT_EXT")4 5# Rule to check if a list of dependencies contains any entrypoint objects. Returns a list in entrypoint_deps.6function(check_entrypoint_deps entrypoint_deps)7  set(PUBLIC_DEPS "")8  set(fq_deps_list "")9  list(APPEND fq_deps_list ${ARGN})10 11  #don't warn for deps that are allowed, such as errno12  set(ALLOWED_DEPS13    "libc.src.errno.errno"14    "libc.src.setjmp.longjmp"15  )16  list(REMOVE_ITEM fq_deps_list ${ALLOWED_DEPS})17 18  foreach(dep IN LISTS fq_deps_list)19    if(NOT TARGET ${dep})20      continue()21    endif()22 23    get_target_property(target_type ${dep} "TARGET_TYPE")24    if(${target_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE})25      list(APPEND PUBLIC_DEPS ${dep})26    endif()27  endforeach()28  set(${entrypoint_deps} ${PUBLIC_DEPS} PARENT_SCOPE)29endfunction()30 31 32# Rule which is essentially a wrapper over add_library to compile a set of33# sources to object files.34# Usage:35#     add_object_library(36#       <target_name>37#       HDRS <list of header files>38#       SRCS <list of source files>39#       [ALIAS] <If this object library is an alias for another object library.>40#       DEPENDS <list of dependencies; Should be a single item for ALIAS libraries>41#       COMPILE_OPTIONS <optional list of special compile options for this target>42#       FLAGS <optional list of flags>43function(create_object_library fq_target_name)44  cmake_parse_arguments(45    "ADD_OBJECT"46    "ALIAS;NO_GPU_BUNDLE" # optional arguments47    "CXX_STANDARD" # Single value arguments48    "SRCS;HDRS;COMPILE_OPTIONS;DEPENDS;FLAGS" # Multivalue arguments49    ${ARGN}50  )51 52  get_fq_deps_list(fq_deps_list ${ADD_OBJECT_DEPENDS})53 54  if(ADD_OBJECT_ALIAS)55    if(ADD_OBJECT_SRCS OR ADD_OBJECT_HDRS)56      message(FATAL_ERROR57              "${fq_target_name}: object library alias cannot have SRCS and/or HDRS.")58    endif()59    list(LENGTH fq_deps_list depends_size)60    if(NOT ${depends_size} EQUAL 1)61      message(FATAL_ERROR62              "${fq_targe_name}: object library alias should have exactly one DEPENDS.")63    endif()64    add_library(65      ${fq_target_name}66      ALIAS67      ${fq_deps_list}68    )69    return()70  endif()71 72  if(NOT ADD_OBJECT_SRCS)73    message(FATAL_ERROR "'add_object_library' rule requires SRCS to be specified.")74  endif()75 76  if(NOT ADD_OBJECT_CXX_STANDARD)77    set(ADD_OBJECT_CXX_STANDARD ${CMAKE_CXX_STANDARD})78  endif()79 80  set(internal_target_name ${fq_target_name}.__internal__)81  set(public_packaging_for_internal "-DLIBC_COPT_PUBLIC_PACKAGING")82 83  _get_common_compile_options(compile_options "${ADD_OBJECT_FLAGS}")84  list(APPEND compile_options ${ADD_OBJECT_COMPILE_OPTIONS})85 86  add_library(87    ${fq_target_name}88    EXCLUDE_FROM_ALL89    OBJECT90    ${ADD_OBJECT_SRCS}91    ${ADD_OBJECT_HDRS}92  )93  target_include_directories(${fq_target_name} SYSTEM PRIVATE ${LIBC_INCLUDE_DIR})94  target_include_directories(${fq_target_name} PRIVATE ${LIBC_SOURCE_DIR})95  target_compile_options(${fq_target_name} PRIVATE ${compile_options})96 97  #loop through the deps, check if any have the TARGET_TYPE of ENTRYPOINT_OBJ_TARGET_TYPE, and print a warning if they do.98  if(LIBC_CMAKE_VERBOSE_LOGGING)99    set(entrypoint_deps "")100    if(NOT "${fq_deps_list}" STREQUAL "")101      check_entrypoint_deps(entrypoint_deps ${fq_deps_list})102    endif()103    if(NOT "${entrypoint_deps}" STREQUAL "")104      message(WARNING "Object ${fq_target_name} depends on public entrypoint(s) ${entrypoint_deps}.105      Depending on public entrypoints is not allowed in internal code.")106    endif()107  endif()108 109  if(SHOW_INTERMEDIATE_OBJECTS)110    message(STATUS "Adding object library ${fq_target_name}")111    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")112      foreach(dep IN LISTS ADD_OBJECT_DEPENDS)113        message(STATUS "  ${fq_target_name} depends on ${dep}")114      endforeach()115    endif()116  endif()117 118  list(APPEND fq_deps_list libc.src.__support.macros.config)119  list(REMOVE_DUPLICATES fq_deps_list)120  add_dependencies(${fq_target_name} ${fq_deps_list})121  # Add deps as link libraries to inherit interface compile and link options.122  target_link_libraries(${fq_target_name} PUBLIC ${fq_deps_list})123 124  set_target_properties(125    ${fq_target_name}126    PROPERTIES127      TARGET_TYPE ${OBJECT_LIBRARY_TARGET_TYPE}128      CXX_STANDARD ${ADD_OBJECT_CXX_STANDARD}129      DEPS "${fq_deps_list}"130      FLAGS "${ADD_OBJECT_FLAGS}"131  )132 133  # If we built a separate internal target we want to use those target objects134  # for testing instead of the exported target.135  set(target_objects ${fq_target_name})136  if(TARGET ${internal_target_name})137    set(target_objects ${internal_target_name})138  endif()139 140  set_target_properties(141    ${fq_target_name}142    PROPERTIES143      OBJECT_FILES "$<TARGET_OBJECTS:${target_objects}>"144  )145endfunction(create_object_library)146 147function(add_object_library target_name)148  add_target_with_flags(149    ${target_name}150    CREATE_TARGET create_object_library151    ${ARGN})152endfunction(add_object_library)153 154 155# A rule for entrypoint object targets.156# Usage:157#     add_entrypoint_object(158#       <target_name>159#       [ALIAS|REDIRECTED] # Specified if the entrypoint is redirected or an alias.160#       [NAME] <the C name of the entrypoint if different from target_name>161#       SRCS <list of .cpp files>162#       HDRS <list of .h files>163#       DEPENDS <list of dependencies>164#       COMPILE_OPTIONS <optional list of special compile options for this target>165#       SPECIAL_OBJECTS <optional list of special object targets added by the rule `add_object`>166#       FLAGS <optional list of flags>167#     )168function(create_entrypoint_object fq_target_name)169  cmake_parse_arguments(170    "ADD_ENTRYPOINT_OBJ"171    "ALIAS;REDIRECTED" # Optional argument172    "NAME;CXX_STANDARD" # Single value arguments173    "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;FLAGS"  # Multi value arguments174    ${ARGN}175  )176 177  set(entrypoint_target_type ${ENTRYPOINT_OBJ_TARGET_TYPE})178  list(FIND TARGET_ENTRYPOINT_NAME_LIST ${ADD_ENTRYPOINT_OBJ_NAME} entrypoint_name_index)179  if(${entrypoint_name_index} EQUAL -1)180    add_custom_target(${fq_target_name})181    set_target_properties(182      ${fq_target_name}183      PROPERTIES184        "ENTRYPOINT_NAME" ${ADD_ENTRYPOINT_OBJ_NAME}185        "TARGET_TYPE" ${entrypoint_target_type}186        "OBJECT_FILE" ""187        "OBJECT_FILE_RAW" ""188        "DEPS" ""189        "SKIPPED" "YES"190    )191    if(LIBC_CMAKE_VERBOSE_LOGGING)192      message(STATUS "Skipping libc entrypoint ${fq_target_name}.")193    endif()194    return()195  endif()196 197  set(internal_target_name ${fq_target_name}.__internal__)198 199  if(ADD_ENTRYPOINT_OBJ_ALIAS)200    # Alias targets help one add aliases to other entrypoint object targets.201    # One can use alias targets setup OS/machine independent entrypoint targets.202    list(LENGTH ADD_ENTRYPOINT_OBJ_DEPENDS deps_size)203    if(NOT (${deps_size} EQUAL "1"))204      message(FATAL_ERROR "An entrypoint alias should have exactly one dependency.")205    endif()206    list(GET ADD_ENTRYPOINT_OBJ_DEPENDS 0 dep_target)207    get_fq_dep_name(fq_dep_name ${dep_target})208 209    if(SHOW_INTERMEDIATE_OBJECTS)210      message(STATUS "Adding entrypoint object ${fq_target_name} as an alias of"211              " ${fq_dep_name}")212    endif()213 214    if(NOT TARGET ${fq_dep_name})215      message(WARNING "Aliasee ${fq_dep_name} for entrypoint alias ${target_name} missing; "216                      "Target ${target_name} will be ignored.")217      return()218    endif()219 220    get_target_property(obj_type ${fq_dep_name} "TARGET_TYPE")221    if((NOT obj_type) OR (NOT ${obj_type} STREQUAL ${ENTRYPOINT_OBJ_TARGET_TYPE}))222      message(FATAL_ERROR "The aliasee of an entrypoint alias should be an entrypoint.")223    endif()224 225    get_target_property(object_file ${fq_dep_name} "OBJECT_FILE")226    get_target_property(object_file_raw ${fq_dep_name} "OBJECT_FILE_RAW")227 228    # If the system cannot build the GPU tests we simply make a dummy target.229    if(LIBC_TARGET_OS_IS_GPU AND LIBC_GPU_TESTS_DISABLED)230      add_custom_target(${internal_target_name})231    else()232      add_library(233        ${internal_target_name}234        EXCLUDE_FROM_ALL235        OBJECT236        ${object_file_raw}237      )238    endif()239 240    add_dependencies(${internal_target_name} ${fq_dep_name})241    add_library(242      ${fq_target_name}243      EXCLUDE_FROM_ALL244      OBJECT245      ${object_file}246    )247    add_dependencies(${fq_target_name} ${fq_dep_name} ${internal_target_name})248    set_target_properties(249      ${fq_target_name}250      PROPERTIES251        ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}252        TARGET_TYPE ${entrypoint_target_type}253        IS_ALIAS "YES"254        OBJECT_FILE ""255        OBJECT_FILE_RAW ""256        DEPS "${fq_dep_name}"257        FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"258    )259    return()260  endif()261 262  if(NOT ADD_ENTRYPOINT_OBJ_SRCS)263    message(FATAL_ERROR "`add_entrypoint_object` rule requires SRCS to be specified.")264  endif()265  if(NOT ADD_ENTRYPOINT_OBJ_CXX_STANDARD)266    set(ADD_ENTRYPOINT_OBJ_CXX_STANDARD ${CMAKE_CXX_STANDARD})267  endif()268 269  _get_common_compile_options(common_compile_options "${ADD_ENTRYPOINT_OBJ_FLAGS}")270  list(APPEND common_compile_options ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS})271  get_fq_deps_list(fq_deps_list ${ADD_ENTRYPOINT_OBJ_DEPENDS})272 273  #loop through the deps, check if any have the TARGET_TYPE of entrypoint_target_type, and print a warning if they do.274  if(LIBC_CMAKE_VERBOSE_LOGGING)275    set(entrypoint_deps "")276    if(NOT "${fq_deps_list}" STREQUAL "")277      check_entrypoint_deps(entrypoint_deps ${fq_deps_list})278    endif()279    if(NOT "${entrypoint_deps}" STREQUAL "")280      message(WARNING "Entrypoint ${fq_target_name} depends on public entrypoint(s) ${entrypoint_deps}.281      Depending on public entrypoints is not allowed in internal code.")282    endif()283  endif()284 285  set(full_deps_list ${fq_deps_list} libc.src.__support.common)286 287  if(SHOW_INTERMEDIATE_OBJECTS)288    message(STATUS "Adding entrypoint object ${fq_target_name}")289    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")290      foreach(dep IN LISTS ADD_ENTRYPOINT_OBJ_DEPENDS)291        message(STATUS "  ${fq_target_name} depends on ${dep}")292      endforeach()293    endif()294  endif()295 296  add_library(297    ${internal_target_name}298    # TODO: We don't need an object library for internal consumption.299    # A future change should switch this to a normal static library.300    EXCLUDE_FROM_ALL301    OBJECT302    ${ADD_ENTRYPOINT_OBJ_SRCS}303    ${ADD_ENTRYPOINT_OBJ_HDRS}304  )305  target_compile_options(${internal_target_name} BEFORE PRIVATE ${common_compile_options})306  target_include_directories(${internal_target_name} SYSTEM PRIVATE ${LIBC_INCLUDE_DIR})307  target_include_directories(${internal_target_name} PRIVATE ${LIBC_SOURCE_DIR})308  add_dependencies(${internal_target_name} ${full_deps_list})309  target_link_libraries(${internal_target_name} ${full_deps_list})310 311  add_library(312    ${fq_target_name}313    # We want an object library as the objects will eventually get packaged into314    # an archive (like libc.a).315    EXCLUDE_FROM_ALL316    OBJECT317    ${ADD_ENTRYPOINT_OBJ_SRCS}318    ${ADD_ENTRYPOINT_OBJ_HDRS}319  )320  target_compile_options(${fq_target_name} BEFORE PRIVATE ${common_compile_options} -DLIBC_COPT_PUBLIC_PACKAGING)321  target_include_directories(${fq_target_name} SYSTEM PRIVATE ${LIBC_INCLUDE_DIR})322  target_include_directories(${fq_target_name} PRIVATE ${LIBC_SOURCE_DIR})323  add_dependencies(${fq_target_name} ${full_deps_list})324  target_link_libraries(${fq_target_name} ${full_deps_list})325 326  # Builtin recognition causes issues when trying to implement the builtin327  # functions themselves. The GPU backends do not use libcalls so we disable the328  # known problematic ones on the entrypoints that implement them.329  if(LIBC_TARGET_OS_IS_GPU)330    set(libc_builtins bcmp strlen memmem bzero memcmp memcpy memmem memmove331                      memset strcmp strstr)332    if(${ADD_ENTRYPOINT_OBJ_NAME} IN_LIST libc_builtins)333      target_compile_options(${fq_target_name} PRIVATE -fno-builtin-${ADD_ENTRYPOINT_OBJ_NAME})334    endif()335  endif()336 337  set_target_properties(338    ${fq_target_name}339    PROPERTIES340      ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}341      TARGET_TYPE ${entrypoint_target_type}342      OBJECT_FILE "$<TARGET_OBJECTS:${fq_target_name}>"343      CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}344      DEPS "${fq_deps_list}"345      FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"346  )347 348  if(TARGET ${internal_target_name})349    set_target_properties(350      ${internal_target_name}351      PROPERTIES352        CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}353        FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"354    )355    set_target_properties(356      ${fq_target_name}357      PROPERTIES358        # TODO: We don't need to list internal object files if the internal359        # target is a normal static library.360        OBJECT_FILE_RAW "$<TARGET_OBJECTS:${internal_target_name}>"361    )362  endif()363 364  if(LLVM_LIBC_ENABLE_LINTING AND TARGET ${internal_target_name})365    if(NOT LLVM_LIBC_CLANG_TIDY)366      message(FATAL_ERROR "Something is wrong!  LLVM_LIBC_ENABLE_LINTING is "367              "ON but LLVM_LIBC_CLANG_TIDY is not set.")368    endif()369 370    # We only want a second invocation of clang-tidy to run371    # restrict-system-libc-headers if the compiler-resource-dir was set in372    # order to prevent false-positives due to a mismatch between the host373    # compiler and the compiled clang-tidy.374    if(COMPILER_RESOURCE_DIR)375      # We run restrict-system-libc-headers with --system-headers to prevent376      # transitive inclusion through compler provided headers.377      set(restrict_system_headers_check_invocation378        COMMAND ${LLVM_LIBC_CLANG_TIDY} --system-headers379        --checks="-*,llvmlibc-restrict-system-libc-headers"380        # We explicitly set the resource dir here to match the381        # resource dir of the host compiler.382        "--extra-arg=-resource-dir=${COMPILER_RESOURCE_DIR}"383        --quiet384        -p ${PROJECT_BINARY_DIR}385        ${ADD_ENTRYPOINT_OBJ_SRCS}386      )387    else()388      set(restrict_system_headers_check_invocation389        COMMAND ${CMAKE_COMMAND} -E echo "Header file check skipped")390    endif()391 392    add_custom_target(393      ${fq_target_name}.__lint__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 some397      # 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 surpress400      # these.401      COMMAND ${LLVM_LIBC_CLANG_TIDY}402              "--extra-arg=-fno-caret-diagnostics" --quiet403              # Path to directory containing compile_commands.json404              -p ${PROJECT_BINARY_DIR}405              ${ADD_ENTRYPOINT_OBJ_SRCS}406      # See above: this might be a second invocation of clang-tidy depending on407      # the conditions above.408      ${restrict_system_headers_check_invocation}409      # We have two options for running commands, add_custom_command and410      # add_custom_target. We don't want to run the linter unless source files411      # have changed. add_custom_target explicitly runs everytime therefore we412      # use add_custom_command. This function requires an output file and since413      # linting doesn't produce a file, we create a dummy file using a414      # crossplatform touch.415      COMMENT "Linting... ${fq_target_name}"416      DEPENDS ${internal_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS}417      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}418    )419    add_dependencies(libc-lint ${fq_target_name}.__lint__)420  endif()421 422endfunction(create_entrypoint_object)423 424function(add_entrypoint_object target_name)425  cmake_parse_arguments(426    "ADD_ENTRYPOINT_OBJ"427    "" # Optional arguments428    "NAME" # Single value arguments429    "" # Multi-value arguments430    ${ARGN}431  )432 433  if(NOT ADD_ENTRYPOINT_OBJ_NAME)434    set(ADD_ENTRYPOINT_OBJ_NAME ${target_name})435  endif()436 437  add_target_with_flags(438    ${target_name}439    NAME ${ADD_ENTRYPOINT_OBJ_NAME}440    CREATE_TARGET create_entrypoint_object441    ${ADD_ENTRYPOINT_OBJ_UNPARSED_ARGUMENTS}442  )443endfunction(add_entrypoint_object)444 445# A rule for external entrypoint targets.446# Usage:447#     add_entrypoint_external(448#       <target_name>449#       DEPENDS <list of dependencies>450#     )451function(add_entrypoint_external target_name)452  cmake_parse_arguments(453    "ADD_ENTRYPOINT_EXT"454    "" # No optional arguments455    "" # No single value arguments456    "DEPENDS"  # Multi value arguments457    ${ARGN}458  )459  get_fq_target_name(${target_name} fq_target_name)460  set(entrypoint_name ${target_name})461 462  add_custom_target(${fq_target_name})463  set_target_properties(464    ${fq_target_name}465    PROPERTIES466      "ENTRYPOINT_NAME" ${entrypoint_name}467      "TARGET_TYPE" ${ENTRYPOINT_EXT_TARGET_TYPE}468      "DEPS" "${ADD_ENTRYPOINT_EXT_DEPENDS}"469  )470 471endfunction(add_entrypoint_external)472 473# Helper to define a function with multiple implementations474# - Computes flags to satisfy required/rejected features and arch,475# - Declares an entry point,476# - Attach the REQUIRE_CPU_FEATURES property to the target,477# - Add the fully qualified target to `${name}_implementations` global property for tests.478function(add_implementation name impl_name)479  cmake_parse_arguments(480    "ADD_IMPL"481    "" # Optional arguments482    "" # Single value arguments483    "REQUIRE;SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;MLLVM_COMPILE_OPTIONS" # Multi value arguments484    ${ARGN})485 486  if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")487    # Note that '-mllvm' needs to be prefixed with 'SHELL:' to prevent CMake flag deduplication.488    foreach(opt IN LISTS ADD_IMPL_MLLVM_COMPILE_OPTIONS)489      list(APPEND ADD_IMPL_COMPILE_OPTIONS "SHELL:-mllvm ${opt}")490    endforeach()491  endif()492 493  if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")494    # Prevent warning when passing x86 SIMD types as template arguments.495    # e.g. "warning: ignoring attributes on template argument ‘__m128i’ [-Wignored-attributes]"496    list(APPEND ADD_IMPL_COMPILE_OPTIONS "-Wno-ignored-attributes")497  endif()498 499  add_entrypoint_object(${impl_name}500    NAME ${name}501    SRCS ${ADD_IMPL_SRCS}502    HDRS ${ADD_IMPL_HDRS}503    DEPENDS ${ADD_IMPL_DEPENDS}504    COMPILE_OPTIONS ${libc_opt_high_flag} ${ADD_IMPL_COMPILE_OPTIONS}505  )506  get_fq_target_name(${impl_name} fq_target_name)507  set_target_properties(${fq_target_name} PROPERTIES REQUIRE_CPU_FEATURES "${ADD_IMPL_REQUIRE}")508  set_property(GLOBAL APPEND PROPERTY "${name}_implementations" "${fq_target_name}")509endfunction()510