brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.1 KiB · 4bbd21a Raw
308 lines · plain
1# In general, a flag is a string provided for supported functions under the2# multi-valued option `FLAGS`.  It should be one of the following forms:3#   FLAG_NAME4#   FLAG_NAME__NO5#   FLAG_NAME__ONLY6# A target will inherit all the flags of its upstream dependency.7#8# When we create a target `TARGET_NAME` with a flag using (add_header_library,9# add_object_library, ...), its behavior will depend on the flag form as follow:10# - FLAG_NAME: The following 2 targets will be generated:11#     `TARGET_NAME` that has `FLAG_NAME` in its `FLAGS` property.12#     `TARGET_NAME.__NO_FLAG_NAME` that depends on `DEP.__NO_FLAG_NAME` if13#        `TARGET_NAME` depends on `DEP` and `DEP` has `FLAG_NAME` in its `FLAGS`14#        property.15# - FLAG_NAME__ONLY: Only generate 1 target `TARGET_NAME` that has `FLAG_NAME`16#     in its `FLAGS` property.17# - FLAG_NAME__NO: Only generate 1 target `TARGET_NAME` that depends on18# `DEP.__NO_FLAG_NAME` if `DEP` is in its DEPENDS list and `DEP` has `FLAG_NAME`19# in its `FLAGS` property.20#21# To show all the targets generated, pass SHOW_INTERMEDIATE_OBJECTS=ON to cmake.22# To show all the targets' dependency and flags, pass23#   SHOW_INTERMEDIATE_OBJECTS=DEPS to cmake.24#25# To completely disable a flag FLAG_NAME expansion, set the variable26#   SKIP_FLAG_EXPANSION_FLAG_NAME=TRUE in this file.27 28 29function(extract_flag_modifier input_flag output_flag modifier)30  if(${input_flag} MATCHES "__NO$")31    string(REGEX REPLACE "__NO$" "" flag "${input_flag}")32    set(${output_flag} ${flag} PARENT_SCOPE)33    set(${modifier} "NO" PARENT_SCOPE)34  elseif(${input_flag} MATCHES "__ONLY$")35    string(REGEX REPLACE "__ONLY$" "" flag "${input_flag}")36    set(${output_flag} ${flag} PARENT_SCOPE)37    set(${modifier} "ONLY" PARENT_SCOPE)38  else()39    set(${output_flag} ${input_flag} PARENT_SCOPE)40    set(${modifier} "" PARENT_SCOPE)41  endif()42endfunction(extract_flag_modifier)43 44function(remove_duplicated_flags input_flags output_flags)45  set(out_flags "")46  foreach(input_flag IN LISTS input_flags)47    if(NOT input_flag)48      continue()49    endif()50 51    extract_flag_modifier(${input_flag} flag modifier)52 53    # Check if the flag is skipped.54    if(${SKIP_FLAG_EXPANSION_${flag}})55      if("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")56        message(STATUS "  Flag ${flag} is ignored.")57      endif()58      continue()59    endif()60 61    set(found FALSE)62    foreach(out_flag IN LISTS out_flags)63      extract_flag_modifier(${out_flag} o_flag o_modifier)64      if("${flag}" STREQUAL "${o_flag}")65        set(found TRUE)66        break()67      endif()68    endforeach()69    if(NOT found)70      list(APPEND out_flags ${input_flag})71    endif()72  endforeach()73 74  set(${output_flags} "${out_flags}" PARENT_SCOPE)75endfunction(remove_duplicated_flags)76 77# Collect flags from dependency list.  To see which flags come with each78# dependence, pass `SHOW_INTERMEDIATE_OBJECTS=DEPS` to cmake.79function(get_flags_from_dep_list output_list)80  set(flag_list "")81  foreach(dep IN LISTS ARGN)82    if(NOT dep)83      continue()84    endif()85 86    get_fq_dep_name(fq_dep_name ${dep})87 88    if(NOT TARGET ${fq_dep_name})89      continue()90    endif()91 92    get_target_property(flags ${fq_dep_name} "FLAGS")93 94    if(flags AND "${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")95      message(STATUS "  FLAGS from dependency ${fq_dep_name} are ${flags}")96    endif()97 98    foreach(flag IN LISTS flags)99      if(flag)100        list(APPEND flag_list ${flag})101      endif()102    endforeach()103  endforeach(dep)104 105  list(REMOVE_DUPLICATES flag_list)106 107  set(${output_list} ${flag_list} PARENT_SCOPE)108endfunction(get_flags_from_dep_list)109 110# Given a `flag` without modifier, scan through the list of dependency, append111# `.__NO_flag` to any target that has `flag` in its FLAGS property.112function(get_fq_dep_list_without_flag output_list flag)113  set(fq_dep_no_flag_list "")114  foreach(dep IN LISTS ARGN)115    get_fq_dep_name(fq_dep_name ${dep})116    if(TARGET ${fq_dep_name})117      get_target_property(dep_flags ${fq_dep_name} "FLAGS")118      # Only target with `flag` has `.__NO_flag` target, `flag__NO` and119      # `flag__ONLY` do not.120      if(${flag} IN_LIST dep_flags)121        list(APPEND fq_dep_no_flag_list "${fq_dep_name}.__NO_${flag}")122      else()123        list(APPEND fq_dep_no_flag_list ${fq_dep_name})124      endif()125    else()126      list(APPEND fq_dep_no_flag_list ${fq_dep_name})127    endif()128  endforeach(dep)129  set(${output_list} ${fq_dep_no_flag_list} PARENT_SCOPE)130endfunction(get_fq_dep_list_without_flag)131 132# Check if a `flag` is set133function(check_flag result flag_name)134  list(FIND ARGN ${flag_name} has_flag)135  if(${has_flag} LESS 0)136    list(FIND ARGN "${flag_name}__ONLY" has_flag)137  endif()138  if(${has_flag} GREATER -1)139    set(${result} TRUE PARENT_SCOPE)140  else()141    set(${result} FALSE PARENT_SCOPE)142  endif()143endfunction(check_flag)144 145# Generate all flags' combinations and call the corresponding function provided146# by `CREATE_TARGET` to create a target for each combination.147function(expand_flags_for_target target_name flags)148  cmake_parse_arguments(149    "EXPAND_FLAGS"150    "" # Optional arguments151    "CREATE_TARGET" # Single-value arguments152    "DEPENDS;FLAGS" # Multi-value arguments153    ${ARGN}154  )155 156  list(LENGTH flags nflags)157  if(NOT ${nflags})158    cmake_language(CALL ${EXPAND_FLAGS_CREATE_TARGET}159      ${target_name}160      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}161      DEPENDS ${EXPAND_FLAGS_DEPENDS}162      FLAGS ${EXPAND_FLAGS_FLAGS}163    )164    return()165  endif()166 167  list(GET flags 0 flag)168  list(REMOVE_AT flags 0)169  extract_flag_modifier(${flag} real_flag modifier)170 171  if(NOT "${modifier}" STREQUAL "NO")172    expand_flags_for_target(173      ${target_name}174      "${flags}"175      DEPENDS ${EXPAND_FLAGS_DEPENDS}176      FLAGS ${EXPAND_FLAGS_FLAGS}177      CREATE_TARGET ${EXPAND_FLAGS_CREATE_TARGET}178      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}179    )180  endif()181 182  if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")183    return()184  endif()185 186  set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})187  list(REMOVE_ITEM NEW_FLAGS ${flag})188  get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})189 190  # Only target with `flag` has `.__NO_flag` target, `flag__NO` and191  # `flag__ONLY` do not.192  if("${modifier}" STREQUAL "")193    set(TARGET_NAME "${target_name}.__NO_${flag}")194  else()195    set(TARGET_NAME "${target_name}")196  endif()197 198  expand_flags_for_target(199    ${TARGET_NAME}200    "${flags}"201    DEPENDS ${NEW_DEPS}202    FLAGS ${NEW_FLAGS}203    CREATE_TARGET ${EXPAND_FLAGS_CREATE_TARGET}204    ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}205  )206endfunction(expand_flags_for_target)207 208# Collect all flags from a target's dependency, and then forward to209# `expand_flags_for_target to generate all flags' combinations and call210# the corresponding function provided by `CREATE_TARGET` to create a target for211# each combination.212function(add_target_with_flags target_name)213  cmake_parse_arguments(214    "ADD_TO_EXPAND"215    "" # Optional arguments216    "CREATE_TARGET;" # Single value arguments217    "DEPENDS;FLAGS;ADD_FLAGS" # Multi-value arguments218    ${ARGN}219  )220 221  if(NOT target_name)222    message(FATAL_ERROR "Bad target name")223  endif()224 225  if(NOT ADD_TO_EXPAND_CREATE_TARGET)226    message(FATAL_ERROR "Missing function to create targets.  Please specify "227                        "`CREATE_TARGET <function>`")228  endif()229 230  get_fq_target_name(${target_name} fq_target_name)231 232  if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))233    message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")234  endif()235 236  get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})237  get_flags_from_dep_list(deps_flag_list ${fq_deps_list})238 239  # Appending ADD_FLAGS before flags from dependency.240  if(ADD_TO_EXPAND_ADD_FLAGS)241    list(APPEND ADD_TO_EXPAND_FLAGS ${ADD_TO_EXPAND_ADD_FLAGS})242  endif()243  list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})244  remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)245  list(SORT flags)246 247  if(SHOW_INTERMEDIATE_OBJECTS AND flags)248    message(STATUS "Target ${fq_target_name} has FLAGS: ${flags}")249  endif()250 251  expand_flags_for_target(252    ${fq_target_name}253    "${flags}"254    DEPENDS "${fq_deps_list}"255    FLAGS "${flags}"256    CREATE_TARGET ${ADD_TO_EXPAND_CREATE_TARGET}257    ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}258  )259endfunction(add_target_with_flags)260 261# Special flags262set(FMA_OPT_FLAG "FMA_OPT")263set(ROUND_OPT_FLAG "ROUND_OPT")264# This flag controls whether we use explicit SIMD instructions or not.265set(EXPLICIT_SIMD_OPT_FLAG "EXPLICIT_SIMD_OPT")266# This flag controls whether we use compiler builtin functions to implement267# various basic math operations or not.268set(MISC_MATH_BASIC_OPS_OPT_FLAG "MISC_MATH_BASIC_OPS_OPT")269 270# Skip FMA_OPT flag for targets that don't support fma.271if(NOT DEFINED SKIP_FLAG_EXPANSION_FMA_OPT)272  if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86_64 AND (LIBC_CPU_FEATURES MATCHES "FMA")) OR273        LIBC_TARGET_ARCHITECTURE_IS_ANY_RISCV))274    set(SKIP_FLAG_EXPANSION_FMA_OPT TRUE)275  endif()276endif()277 278# Skip EXPLICIT_SIMD_OPT flag for targets that don't support SSE2.279# Note: one may want to revisit it if they want to control other explicit SIMD280if(NOT DEFINED SKIP_FLAG_EXPANSION_EXPLICIT_SIMD_OPT)281  if(NOT(LIBC_TARGET_ARCHITECTURE_IS_X86_64 AND (LIBC_CPU_FEATURES MATCHES "SSE2")))282    set(SKIP_FLAG_EXPANSION_EXPLICIT_SIMD_OPT TRUE)283  endif()284endif()285 286# Skip ROUND_OPT flag for targets that don't support rounding instructions. On287# x86, these are SSE4.1 instructions, but we already had code to check for288# SSE4.2 support.289if(NOT DEFINED SKIP_FLAG_EXPANSION_ROUND_OPT)290  if(NOT((LIBC_TARGET_ARCHITECTURE_IS_X86_64 AND (LIBC_CPU_FEATURES MATCHES "SSE4_2")) OR291        LIBC_TARGET_ARCHITECTURE_IS_AARCH64 OR LIBC_TARGET_OS_IS_GPU))292    set(SKIP_FLAG_EXPANSION_ROUND_OPT TRUE)293  endif()294endif()295 296# Choose whether time_t is 32- or 64-bit, based on target architecture297# and config options. This will be used to set a #define during the298# library build, and also to select the right version of time_t.h for299# the output headers.300if(LIBC_TARGET_ARCHITECTURE_IS_ARM AND NOT (LIBC_CONF_TIME_64BIT))301  # Set time_t to 32 bit for compatibility with glibc, unless302  # configuration says otherwise303  set(LIBC_TYPES_TIME_T_IS_32_BIT TRUE)304else()305  # Other platforms default to 64-bit time_t306  set(LIBC_TYPES_TIME_T_IS_32_BIT FALSE)307endif()308