[libc-commits] [libc] 8000514 - [libc] Implement FLAGS option for generating all combinations for targets.

Tue Ly via libc-commits libc-commits at lists.llvm.org
Tue May 31 21:54:30 PDT 2022


Author: Tue Ly
Date: 2022-06-01T00:54:07-04:00
New Revision: 800051487f13e5506502c0c4021a97a53b89bcde

URL: https://github.com/llvm/llvm-project/commit/800051487f13e5506502c0c4021a97a53b89bcde
DIFF: https://github.com/llvm/llvm-project/commit/800051487f13e5506502c0c4021a97a53b89bcde.diff

LOG: [libc] Implement FLAGS option for generating all combinations for targets.

Add FLAGS option for add_header_library, add_object_library,
add_entrypoint_object, and add_libc_unittest.

In general, a flag is a string provided for supported functions under the
multi-valued option `FLAGS`.  It should be one of the following forms:
  FLAG_NAME
  FLAG_NAME__NO
  FLAG_NAME__ONLY
A target will inherit all the flags of its upstream dependency.

When we create a target `TARGET_NAME` with a flag using (add_header_library,
add_object_library, ...), its behavior will depend on the flag form as follow:
- FLAG_NAME: The following 2 targets will be generated:
    `TARGET_NAME` that has `FLAG_NAME` in its `FLAGS` property.
    `TARGET_NAME.__NO_FLAG_NAME` that depends on `DEP.__NO_FLAG_NAME` if
       `TARGET_NAME` depends on `DEP` and `DEP` has `FLAG_NAME` in its `FLAGS`
       property.
- FLAG_NAME__ONLY: Only generate 1 target `TARGET_NAME` that has `FLAG_NAME`
    in its `FLAGS` property.
- FLAG_NAME__NO: Only generate 1 target `TARGET_NAME.__NO_FLAG_NAME` that
    depends on `DEP.__NO_FLAG_NAME` if `DEP` is in its DEPENDS list and `DEP`
    has `FLAG_NAME` in its `FLAGS` property.

To show all the targets generated, pass SHOW_INTERMEDIATE_OBJECTS=ON to cmake.
To show all the targets' dependency and flags, pass
`SHOW_INTERMEDIATE_OBJECTS=DEPS` to cmake.

To completely disable a flag FLAG_NAME expansion, set the variable
`SKIP_FLAG_EXPANSION_FLAG_NAME=TRUE`.

Reviewed By: michaelrj, sivachandra

Differential Revision: https://reviews.llvm.org/D125174

Added: 
    libc/cmake/modules/LLVMLibCFlagRules.cmake

Modified: 
    libc/CMakeLists.txt
    libc/cmake/modules/LLVMLibCLibraryRules.cmake
    libc/cmake/modules/LLVMLibCObjectRules.cmake
    libc/cmake/modules/LLVMLibCRules.cmake
    libc/cmake/modules/LLVMLibCTestRules.cmake
    libc/test/src/CMakeLists.txt
    libc/test/src/__support/File/CMakeLists.txt
    libc/test/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
    libc/test/src/math/exhaustive/CMakeLists.txt
    libc/test/src/stdio/printf_core/CMakeLists.txt
    libc/test/src/string/CMakeLists.txt
    libc/test/src/string/memory_utils/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index ca9a81991fa98..30d7c33c2ce9b 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -105,8 +105,8 @@ endif()
 option(LIBC_INCLUDE_DOCS "Build the libc documentation." ${LLVM_INCLUDE_DOCS})
 
 include(CMakeParseArguments)
-include(LLVMLibCRules)
 include(LLVMLibCCheckCpuFeatures)
+include(LLVMLibCRules)
 
 if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/entrypoints.txt")
   set(entrypoint_file "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/entrypoints.txt")

diff  --git a/libc/cmake/modules/LLVMLibCFlagRules.cmake b/libc/cmake/modules/LLVMLibCFlagRules.cmake
new file mode 100644
index 0000000000000..f43b6459bb03a
--- /dev/null
+++ b/libc/cmake/modules/LLVMLibCFlagRules.cmake
@@ -0,0 +1,133 @@
+# In general, a flag is a string provided for supported functions under the
+# multi-valued option `FLAGS`.  It should be one of the following forms:
+#   FLAG_NAME
+#   FLAG_NAME__NO
+#   FLAG_NAME__ONLY
+# A target will inherit all the flags of its upstream dependency.
+#
+# When we create a target `TARGET_NAME` with a flag using (add_header_library,
+# add_object_library, ...), its behavior will depend on the flag form as follow:
+# - FLAG_NAME: The following 2 targets will be generated:
+#     `TARGET_NAME` that has `FLAG_NAME` in its `FLAGS` property.
+#     `TARGET_NAME.__NO_FLAG_NAME` that depends on `DEP.__NO_FLAG_NAME` if
+#        `TARGET_NAME` depends on `DEP` and `DEP` has `FLAG_NAME` in its `FLAGS`
+#        property.
+# - FLAG_NAME__ONLY: Only generate 1 target `TARGET_NAME` that has `FLAG_NAME`
+#     in its `FLAGS` property.
+# - FLAG_NAME__NO: Only generate 1 target `TARGET_NAME` that depends on
+# `DEP.__NO_FLAG_NAME` if `DEP` is in its DEPENDS list and `DEP` has `FLAG_NAME`
+# in its `FLAGS` property.
+#
+# To show all the targets generated, pass SHOW_INTERMEDIATE_OBJECTS=ON to cmake.
+# To show all the targets' dependency and flags, pass
+#   SHOW_INTERMEDIATE_OBJECTS=DEPS to cmake.
+#
+# To completely disable a flag FLAG_NAME expansion, set the variable
+#   SKIP_FLAG_EXPANSION_FLAG_NAME=TRUE in this file.
+
+
+function(extract_flag_modifier input_flag output_flag modifier)
+  if(${input_flag} MATCHES "__NO$")
+    string(REGEX REPLACE "__NO$" "" flag "${input_flag}")
+    set(${output_flag} ${flag} PARENT_SCOPE)
+    set(${modifier} "NO" PARENT_SCOPE)
+  elseif(${input_flag} MATCHES "__ONLY$")
+    string(REGEX REPLACE "__ONLY$" "" flag "${input_flag}")
+    set(${output_flag} ${flag} PARENT_SCOPE)
+    set(${modifier} "ONLY" PARENT_SCOPE)
+  else()
+    set(${output_flag} ${input_flag} PARENT_SCOPE)
+    set(${modifier} "" PARENT_SCOPE)
+  endif()
+endfunction(extract_flag_modifier)
+
+function(remove_duplicated_flags input_flags output_flags)
+  set(out_flags "")
+  foreach(input_flag IN LISTS input_flags)
+    if(NOT input_flag)
+      continue()
+    endif()
+
+    extract_flag_modifier(${input_flag} flag modifier)
+
+    # Check if the flag is skipped.
+    if(${SKIP_FLAG_EXPANSION_${flag}})
+      if("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")
+        message(STATUS "  Flag ${flag} is ignored.")
+      endif()
+      continue()
+    endif()
+
+    set(found FALSE)
+    foreach(out_flag IN LISTS out_flags)
+      extract_flag_modifier(${out_flag} o_flag o_modifier)
+      if("${flag}" STREQUAL "${o_flag}")
+        set(found TRUE)
+        break()
+      endif()
+    endforeach()
+    if(NOT found)
+      list(APPEND out_flags ${input_flag})
+    endif()
+  endforeach()
+
+  set(${output_flags} "${out_flags}" PARENT_SCOPE)
+endfunction(remove_duplicated_flags)
+
+# Collect flags from dependency list.  To see which flags come with each
+# dependence, pass `SHOW_INTERMEDIATE_OBJECTS=DEPS` to cmake.
+function(get_flags_from_dep_list output_list)
+  set(flag_list "")
+  foreach(dep IN LISTS ARGN)
+    if(NOT dep)
+      continue()
+    endif()
+
+    get_fq_dep_name(fq_dep_name ${dep})
+
+    if(NOT TARGET ${fq_dep_name})
+      continue()
+    endif()
+
+    get_target_property(flags ${fq_dep_name} "FLAGS")
+
+    if(flags AND "${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")
+      message(STATUS "  FLAGS from dependency ${fq_dep_name} are ${flags}")
+    endif()
+
+    foreach(flag IN LISTS flags)
+      if(flag)
+        list(APPEND flag_list ${flag})
+      endif()
+    endforeach()
+  endforeach(dep)
+
+  list(REMOVE_DUPLICATES flag_list)
+
+  set(${output_list} ${flag_list} PARENT_SCOPE)
+endfunction(get_flags_from_dep_list)
+
+# Given a `flag` without modifier, scan through the list of dependency, append
+# `.__NO_flag` to any target that has `flag` in its FLAGS property.
+function(get_fq_dep_list_without_flag output_list flag)
+  set(fq_dep_no_flag_list "")
+  foreach(dep IN LISTS ARGN)
+    get_fq_dep_name(fq_dep_name ${dep})
+    if(TARGET ${fq_dep_name})
+      get_target_property(dep_flags ${fq_dep_name} "FLAGS")
+      # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
+      # `flag__ONLY` do not.
+      if(${flag} IN_LIST dep_flags)
+        list(APPEND fq_dep_no_flag_list "${fq_dep_name}.__NO_${flag}")
+      else()
+        list(APPEND fq_dep_no_flag_list ${fq_dep_name})
+      endif()
+    else()
+      list(APPEND fq_dep_no_flag_list ${fq_dep_name})
+    endif()
+  endforeach(dep)
+  set(${output_list} ${fq_dep_no_flag_list} PARENT_SCOPE)
+endfunction(get_fq_dep_list_without_flag)
+
+# Special flags
+set(FMA_OPT_FLAG "FMA_OPT")

diff  --git a/libc/cmake/modules/LLVMLibCLibraryRules.cmake b/libc/cmake/modules/LLVMLibCLibraryRules.cmake
index 5d7c6549796a4..78362cee99bdc 100644
--- a/libc/cmake/modules/LLVMLibCLibraryRules.cmake
+++ b/libc/cmake/modules/LLVMLibCLibraryRules.cmake
@@ -124,19 +124,13 @@ endfunction(add_redirector_library)
 
 set(HDR_LIBRARY_TARGET_TYPE "HDR_LIBRARY")
 
-# Rule to add header only libraries.
-# Usage
-#    add_header_library(
-#      <target name>
-#      HDRS  <list of .h files part of the library>
-#      DEPENDS <list of dependencies>
-#    )
-function(add_header_library target_name)
+# Internal function, used by `add_header_library`.
+function(create_header_library fq_target_name)
   cmake_parse_arguments(
     "ADD_HEADER"
-    "" # No optional arguments
-    "" # No Single value arguments
-    "HDRS;DEPENDS" # Multi-value arguments
+    "" # Optional arguments
+    "" # Single value arguments
+    "HDRS;DEPENDS;FLAGS" # Multi-value arguments
     ${ARGN}
   )
 
@@ -144,8 +138,6 @@ function(add_header_library target_name)
     message(FATAL_ERROR "'add_header_library' target requires a HDRS list of .h files.")
   endif()
 
-  get_fq_target_name(${target_name} fq_target_name)
-
   set(FULL_HDR_PATHS "")
   # TODO: Remove this foreach block when we can switch to the new
   # version of the CMake policy CMP0076.
@@ -153,21 +145,137 @@ function(add_header_library target_name)
     list(APPEND FULL_HDR_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${hdr})
   endforeach()
 
+  if(SHOW_INTERMEDIATE_OBJECTS)
+    message(STATUS "Adding header library ${fq_target_name}")
+    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+      foreach(dep IN LISTS ADD_HEADER_DEPENDS)
+        message(STATUS "  ${fq_target_name} depends on ${dep}")
+      endforeach()
+    endif()
+  endif()
   set(interface_target_name "${fq_target_name}.__header_library__")
 
   add_library(${interface_target_name} INTERFACE)
   target_sources(${interface_target_name} INTERFACE ${FULL_HDR_PATHS})
-  get_fq_deps_list(fq_deps_list ${ADD_HEADER_DEPENDS})
   if(ADD_HEADER_DEPENDS)
-    add_dependencies(${interface_target_name} ${fq_deps_list})
+    add_dependencies(${interface_target_name} ${ADD_HEADER_DEPENDS})
   endif()
+  set_target_properties(
+    ${interface_target_name}
+    PROPERTIES
+      INTERFACE_FLAGS "${ADD_HEADER_FLAGS}"
+  )
 
   add_custom_target(${fq_target_name})
   add_dependencies(${fq_target_name} ${interface_target_name})
   set_target_properties(
     ${fq_target_name}
     PROPERTIES
-      "TARGET_TYPE" "${HDR_LIBRARY_TARGET_TYPE}"
-      "DEPS" "${fq_deps_list}"
+      TARGET_TYPE "${HDR_LIBRARY_TARGET_TYPE}"
+      DEPS "${ADD_HEADER_DEPENDS}"
+      FLAGS "${ADD_HEADER_FLAGS}"
+  )
+endfunction(create_header_library)
+
+# Rule to add header only libraries.
+# Usage
+#    add_header_library(
+#      <target name>
+#      HDRS  <list of .h files part of the library>
+#      DEPENDS <list of dependencies>
+#      FLAGS <list of flags>
+#    )
+
+# Internal function, used by `add_header_library`.
+function(expand_flags_for_header_library target_name flags)
+  cmake_parse_arguments(
+    "EXPAND_FLAGS"
+    "IGNORE_MARKER" # Optional arguments
+    "" # Single-value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  list(LENGTH flags nflags)
+  if(NOT ${nflags})
+    create_header_library(
+      ${target_name}
+      DEPENDS ${EXPAND_FLAGS_DEPENDS}
+      FLAGS ${EXPAND_FLAGS_FLAGS}
+      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
+    )
+    return()
+  endif()
+
+  list(POP_FRONT flags flag)
+  extract_flag_modifier(${flag} real_flag modifier)
+
+  if(NOT "${modifier}" STREQUAL "NO")
+    expand_flags_for_header_library(
+      ${target_name}
+      "${flags}"
+      DEPENDS ${EXPAND_FLAGS_DEPENDS} IGNORE_MARKER
+      FLAGS ${EXPAND_FLAGS_FLAGS} IGNORE_MARKER
+      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
+    )
+  endif()
+
+  if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")
+    return()
+  endif()
+
+  set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})
+  list(REMOVE_ITEM NEW_FLAGS ${flag})
+  get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})
+
+  # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
+  # `flag__ONLY` do not.
+  if(NOT "${modifier}")
+    set(TARGET_NAME "${target_name}.__NO_${flag}")
+  else()
+    set(TARGET_NAME "${target_name}")
+  endif()
+
+  expand_flags_for_header_library(
+    ${TARGET_NAME}
+    "${flags}"
+    DEPENDS ${NEW_DEPS} IGNORE_MARKER
+    FLAGS ${NEW_FLAGS} IGNORE_MARKER
+    ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
+  )
+endfunction(expand_flags_for_header_library)
+
+function(add_header_library target_name)
+  cmake_parse_arguments(
+    "ADD_TO_EXPAND"
+    "" # Optional arguments
+    "" # Single value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  get_fq_target_name(${target_name} fq_target_name)
+
+  if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))
+    message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")
+  endif()
+
+  get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})
+  get_flags_from_dep_list(deps_flag_list ${fq_deps_list})
+  
+  list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})
+  remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)
+  list(SORT flags)
+
+  if(SHOW_INTERMEDIATE_OBJECTS AND flags)
+    message(STATUS "Header library ${fq_target_name} has FLAGS: ${flags}")
+  endif()
+
+  expand_flags_for_header_library(
+    ${fq_target_name}
+    "${flags}"
+    DEPENDS ${fq_deps_list} IGNORE_MARKER
+    FLAGS ${flags} IGNORE_MARKER
+    ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
   )
 endfunction(add_header_library)

diff  --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake
index 8e2f489752a64..ae49e136615e2 100644
--- a/libc/cmake/modules/LLVMLibCObjectRules.cmake
+++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake
@@ -1,7 +1,7 @@
 set(OBJECT_LIBRARY_TARGET_TYPE "OBJECT_LIBRARY")
 
 function(_get_common_compile_options output_var)
-  set(compile_options ${LLVM_CXX_STD_default} ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN})
+  set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN})
   if(NOT ${LIBC_TARGET_OS} STREQUAL "windows")
     set(compile_options ${compile_options} -fpie -ffreestanding)
   endif()
@@ -26,12 +26,13 @@ endfunction()
 #       SRCS <list of source files>
 #       DEPENDS <list of dependencies>
 #       COMPILE_OPTIONS <optional list of special compile options for this target>
-function(add_object_library target_name)
+#       FLAGS <optional list of flags>
+function(create_object_library fq_target_name)
   cmake_parse_arguments(
     "ADD_OBJECT"
     "" # No optional arguments
     "CXX_STANDARD" # Single value arguments
-    "SRCS;HDRS;COMPILE_OPTIONS;DEPENDS" # Multivalue arguments
+    "SRCS;HDRS;COMPILE_OPTIONS;DEPENDS;FLAGS" # Multivalue arguments
     ${ARGN}
   )
 
@@ -39,7 +40,6 @@ function(add_object_library target_name)
     message(FATAL_ERROR "'add_object_library' rule requires SRCS to be specified.")
   endif()
 
-  get_fq_target_name(${target_name} fq_target_name)
   add_library(
     ${fq_target_name}
     EXCLUDE_FROM_ALL
@@ -58,24 +58,126 @@ function(add_object_library target_name)
   target_compile_options(${fq_target_name} PRIVATE ${compile_options})
 
   get_fq_deps_list(fq_deps_list ${ADD_OBJECT_DEPENDS})
+
+  if(SHOW_INTERMEDIATE_OBJECTS)
+    message(STATUS "Adding object library ${fq_target_name}")
+    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+      foreach(dep IN LISTS ADD_OBJECT_DEPENDS)
+        message(STATUS "  ${fq_target_name} depends on ${dep}")
+      endforeach()
+    endif()
+  endif()
+
   if(fq_deps_list)
     add_dependencies(${fq_target_name} ${fq_deps_list})
   endif()
 
-  if(ADD_OBJECT_CXX_STANDARD)
-    set_target_properties(
-      ${fq_target_name}
-      PROPERTIES
-        CXX_STANDARD ${ADD_OBJECT_CXX_STANDARD}
-    )
+  if(NOT ADD_OBJECT_CXX_STANDARD)
+    set(ADD_OBJECT_CXX_STANDARD ${CMAKE_CXX_STANDARD})
   endif()
-
+  
   set_target_properties(
     ${fq_target_name}
     PROPERTIES
-      "TARGET_TYPE" ${OBJECT_LIBRARY_TARGET_TYPE}
-      "OBJECT_FILES" "$<TARGET_OBJECTS:${fq_target_name}>"
-      "DEPS" "${fq_deps_list}"
+      TARGET_TYPE ${OBJECT_LIBRARY_TARGET_TYPE}
+      OBJECT_FILES "$<TARGET_OBJECTS:${fq_target_name}>"
+      CXX_STANDARD ${ADD_OBJECT_CXX_STANDARD}
+      DEPS "${fq_deps_list}"
+      FLAGS "${ADD_OBJECT_FLAGS}"
+  )
+endfunction(create_object_library)
+
+# Internal function, used by `add_object_library`.
+function(expand_flags_for_object_library target_name flags)
+  cmake_parse_arguments(
+    "EXPAND_FLAGS"
+    "IGNORE_MARKER" # Optional arguments
+    "" # Single-value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  list(LENGTH flags nflags)
+  if(NOT ${nflags})
+    create_object_library(
+      ${target_name}
+      DEPENDS ${EXPAND_FLAGS_DEPENDS}
+      FLAGS ${EXPAND_FLAGS_FLAGS}
+      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
+    )
+    return()
+  endif()
+
+  list(POP_FRONT flags flag)
+  extract_flag_modifier(${flag} real_flag modifier)
+
+  if(NOT "${modifier}" STREQUAL "NO")
+    expand_flags_for_object_library(
+      ${target_name}
+      "${flags}"
+      DEPENDS "${EXPAND_FLAGS_DEPENDS}" IGNORE_MARKER
+      FLAGS "${EXPAND_FLAGS_FLAGS}" IGNORE_MARKER
+      "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
+    )
+  endif()
+
+  if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")
+    return()
+  endif()
+
+  set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})
+  list(REMOVE_ITEM NEW_FLAGS ${flag})
+  get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})
+
+  # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
+  # `flag__ONLY` do not.
+  if(NOT "${modifier}")
+    set(TARGET_NAME "${target_name}.__NO_${flag}")
+  else()
+    set(TARGET_NAME "${target_name}")
+  endif()
+
+  expand_flags_for_object_library(
+    ${TARGET_NAME}
+    "${flags}"
+    DEPENDS "${NEW_DEPS}" IGNORE_MARKER
+    FLAGS "${NEW_FLAGS}" IGNORE_MARKER
+    "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
+  )
+endfunction(expand_flags_for_object_library)
+
+function(add_object_library target_name)
+  cmake_parse_arguments(
+    "ADD_TO_EXPAND"
+    "" # Optional arguments
+    "" # Single value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  get_fq_target_name(${target_name} fq_target_name)
+
+  if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))
+    message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")
+  endif()
+
+  get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})
+  get_flags_from_dep_list(deps_flag_list ${fq_deps_list})
+
+  list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})
+  remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)
+  list(SORT flags)
+
+  if(SHOW_INTERMEDIATE_OBJECTS AND flags)
+    message(STATUS "Object library ${fq_target_name} has FLAGS: ${flags}")
+  endif()
+
+  expand_flags_for_object_library(
+    ${fq_target_name}
+    "${flags}"
+    DEPENDS "${fq_deps_list}" IGNORE_MARKER
+    FLAGS "${flags}" IGNORE_MARKER
+    ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
   )
 endfunction(add_object_library)
 
@@ -92,29 +194,24 @@ set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
 #       DEPENDS <list of dependencies>
 #       COMPILE_OPTIONS <optional list of special compile options for this target>
 #       SPECIAL_OBJECTS <optional list of special object targets added by the rule `add_object`>
+#       FLAGS <optional list of flags>
 #     )
-function(add_entrypoint_object target_name)
+function(create_entrypoint_object fq_target_name)
   cmake_parse_arguments(
     "ADD_ENTRYPOINT_OBJ"
     "ALIAS;REDIRECTED" # Optional argument
     "NAME;CXX_STANDARD" # Single value arguments
-    "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS"  # Multi value arguments
+    "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;FLAGS"  # Multi value arguments
     ${ARGN}
   )
 
-  get_fq_target_name(${target_name} fq_target_name)
-  set(entrypoint_name ${target_name})
-  if(ADD_ENTRYPOINT_OBJ_NAME)
-    set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME})
-  endif()
-
-  list(FIND TARGET_ENTRYPOINT_NAME_LIST ${entrypoint_name} entrypoint_name_index)
+  list(FIND TARGET_ENTRYPOINT_NAME_LIST ${ADD_ENTRYPOINT_OBJ_NAME} entrypoint_name_index)
   if(${entrypoint_name_index} EQUAL -1)
     add_custom_target(${fq_target_name})
     set_target_properties(
       ${fq_target_name}
       PROPERTIES
-        "ENTRYPOINT_NAME" ${entrypoint_name}
+        "ENTRYPOINT_NAME" ${ADD_ENTRYPOINT_OBJ_NAME}
         "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
         "OBJECT_FILE" ""
         "OBJECT_FILE_RAW" ""
@@ -134,6 +231,12 @@ function(add_entrypoint_object target_name)
     endif()
     list(GET ADD_ENTRYPOINT_OBJ_DEPENDS 0 dep_target)
     get_fq_dep_name(fq_dep_name ${dep_target})
+
+    if(SHOW_INTERMEDIATE_OBJECTS)
+      message(STATUS "Adding entrypoint object ${fq_target_name} as an alias of"
+              " ${fq_dep_name}")
+    endif()
+
     if(NOT TARGET ${fq_dep_name})
       message(WARNING "Aliasee ${fq_dep_name} for entrypoint alias ${target_name} missing; "
                       "Target ${target_name} will be ignored.")
@@ -152,12 +255,13 @@ function(add_entrypoint_object target_name)
     set_target_properties(
       ${fq_target_name}
       PROPERTIES
-        "ENTRYPOINT_NAME" ${entrypoint_name}
-        "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
-        "IS_ALIAS" "YES"
-        "OBJECT_FILE" ""
-        "OBJECT_FILE_RAW" ""
-        "DEPS" "${fq_dep_name}"
+        ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}
+        TARGET_TYPE ${ENTRYPOINT_OBJ_TARGET_TYPE}
+        IS_ALIAS "YES"
+        OBJECT_FILE ""
+        OBJECT_FILE_RAW ""
+        DEPS "${fq_dep_name}"
+        FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
     )
     return()
   endif()
@@ -168,6 +272,9 @@ function(add_entrypoint_object target_name)
   if(NOT ADD_ENTRYPOINT_OBJ_HDRS)
     message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.")
   endif()
+  if(NOT ADD_ENTRYPOINT_OBJ_CXX_STANDARD)
+    set(ADD_ENTRYPOINT_OBJ_CXX_STANDARD ${CMAKE_CXX_STANDARD})
+  endif()
 
   _get_common_compile_options(common_compile_options ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS})
   set(internal_target_name ${fq_target_name}.__internal__)
@@ -175,6 +282,15 @@ function(add_entrypoint_object target_name)
   get_fq_deps_list(fq_deps_list ${ADD_ENTRYPOINT_OBJ_DEPENDS})
   set(full_deps_list ${fq_deps_list} libc.src.__support.common)
 
+  if(SHOW_INTERMEDIATE_OBJECTS)
+    message(STATUS "Adding entrypoint object ${fq_target_name}")
+    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+      foreach(dep IN LISTS ADD_OBJECT_DEPENDS)
+        message(STATUS "  ${fq_target_name} depends on ${dep}")
+      endforeach()
+    endif()
+  endif()
+
   add_library(
     ${internal_target_name}
     # TODO: We don't need an object library for internal consumption.
@@ -187,6 +303,12 @@ function(add_entrypoint_object target_name)
   target_compile_options(${internal_target_name} BEFORE PRIVATE ${common_compile_options})
   target_include_directories(${internal_target_name} PRIVATE ${include_dirs})
   add_dependencies(${internal_target_name} ${full_deps_list})
+  set_target_properties(
+    ${internal_target_name}
+    PROPERTIES
+      CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
+      FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
+  )
 
   add_library(
     ${fq_target_name}
@@ -201,24 +323,18 @@ function(add_entrypoint_object target_name)
   target_include_directories(${fq_target_name} PRIVATE ${include_dirs})
   add_dependencies(${fq_target_name} ${full_deps_list})
 
-  if(ADD_ENTRYPOINT_OBJ_CXX_STANDARD)
-    set_target_properties(
-      ${fq_target_name} ${internal_target_name}
-      PROPERTIES
-        CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
-    )
-  endif()
-
   set_target_properties(
     ${fq_target_name}
     PROPERTIES
-      "ENTRYPOINT_NAME" ${entrypoint_name}
-      "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
-      "OBJECT_FILE" $<TARGET_OBJECTS:${fq_target_name}>
+      ENTRYPOINT_NAME ${ADD_ENTRYPOINT_OBJ_NAME}
+      TARGET_TYPE ${ENTRYPOINT_OBJ_TARGET_TYPE}
+      OBJECT_FILE "$<TARGET_OBJECTS:${fq_target_name}>"
       # TODO: We don't need to list internal object files if the internal
       # target is a normal static library.
-      "OBJECT_FILE_RAW" $<TARGET_OBJECTS:${internal_target_name}>
-      "DEPS" "${fq_deps_list}"
+      OBJECT_FILE_RAW "$<TARGET_OBJECTS:${internal_target_name}>"
+      CXX_STANDARD ${ADD_ENTRYPOINT_OBJ_CXX_STANDARD}
+      DEPS "${fq_deps_list}"
+      FLAGS "${ADD_ENTRYPOINT_OBJ_FLAGS}"
   )
 
   if(LLVM_LIBC_ENABLE_LINTING)
@@ -280,6 +396,105 @@ function(add_entrypoint_object target_name)
     )
   endif()
 
+endfunction(create_entrypoint_object)
+
+# Internal function, used by `add_entrypoint_object`.
+function(expand_flags_for_entrypoint_object target_name flags)
+  cmake_parse_arguments(
+    "EXPAND_FLAGS"
+    "IGNORE_MARKER" # Optional arguments
+    "" # Single-value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  list(LENGTH flags nflags)
+  if(NOT ${nflags})
+    create_entrypoint_object(
+      ${target_name}
+      DEPENDS ${EXPAND_FLAGS_DEPENDS}
+      FLAGS ${EXPAND_FLAGS_FLAGS}
+      ${EXPAND_FLAGS_UNPARSED_ARGUMENTS}
+    )
+    return()
+  endif()
+
+  list(POP_FRONT flags flag)
+  extract_flag_modifier(${flag} real_flag modifier)
+
+  if(NOT "${modifier}" STREQUAL "NO")
+    expand_flags_for_entrypoint_object(
+      ${target_name}
+      "${flags}"
+      DEPENDS "${EXPAND_FLAGS_DEPENDS}" IGNORE_MARKER
+      FLAGS "${EXPAND_FLAGS_FLAGS}" IGNORE_MARKER
+      "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
+    )
+  endif()
+
+  if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")
+    return()
+  endif()
+
+  set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})
+  list(REMOVE_ITEM NEW_FLAGS ${flag})
+  get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})
+
+  # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
+  # `flag__ONLY` do not.
+  if(NOT "${modifier}")
+    set(TARGET_NAME "${target_name}.__NO_${flag}")
+  else()
+    set(TARGET_NAME "${target_name}")
+  endif()
+
+  expand_flags_for_entrypoint_object(
+    ${TARGET_NAME}
+    "${flags}"
+    DEPENDS "${NEW_DEPS}" IGNORE_MARKER
+    FLAGS "${NEW_FLAGS}" IGNORE_MARKER
+    "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
+  )
+endfunction(expand_flags_for_entrypoint_object)
+
+function(add_entrypoint_object target_name)
+  cmake_parse_arguments(
+    "ADD_TO_EXPAND"
+    "" # Optional arguments
+    "NAME" # Single value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  get_fq_target_name(${target_name} fq_target_name)
+
+  if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))
+    message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")
+  endif()
+
+  get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})
+  get_flags_from_dep_list(deps_flag_list ${fq_deps_list})
+
+  list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})
+  remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)
+  list(SORT flags)
+
+  if(SHOW_INTERMEDIATE_OBJECTS AND flags)
+    message(STATUS "Object library ${fq_target_name} has FLAGS: ${flags}")
+  endif()
+
+  if(NOT ADD_TO_EXPAND_NAME)
+    set(ADD_TO_EXPAND_NAME ${target_name})
+  endif()
+
+  expand_flags_for_entrypoint_object(
+    ${fq_target_name}
+    "${flags}"
+    NAME ${ADD_TO_EXPAND_NAME} IGNORE_MARKER
+    DEPENDS "${fq_deps_list}" IGNORE_MARKER
+    FLAGS "${flags}" IGNORE_MARKER
+    ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
+  )
 endfunction(add_entrypoint_object)
 
 set(ENTRYPOINT_EXT_TARGET_TYPE "ENTRYPOINT_EXT")

diff  --git a/libc/cmake/modules/LLVMLibCRules.cmake b/libc/cmake/modules/LLVMLibCRules.cmake
index f76d6e522b4a5..c45a3f6491174 100644
--- a/libc/cmake/modules/LLVMLibCRules.cmake
+++ b/libc/cmake/modules/LLVMLibCRules.cmake
@@ -1,4 +1,5 @@
 include(LLVMLibCTargetNameUtils)
+include(LLVMLibCFlagRules)
 include(LLVMLibCHeaderRules)
 include(LLVMLibCObjectRules)
 include(LLVMLibCLibraryRules)

diff  --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index b1a34fed63b75..cd4b7b7213331 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -65,7 +65,7 @@ endfunction(get_object_files_for_test)
 #      COMPILE_OPTIONS <list of special compile options for this target>
 #      LINK_LIBRARIES <list of linking libraries for this target>
 #    )
-function(add_libc_unittest target_name)
+function(create_libc_unittest fq_target_name)
   if(NOT LLVM_INCLUDE_TESTS)
     return()
   endif()
@@ -74,7 +74,7 @@ function(add_libc_unittest target_name)
     "LIBC_UNITTEST"
     "NO_RUN_POSTBUILD;NO_LIBC_UNITTEST_TEST_MAIN" # Optional arguments
     "SUITE;CXX_STANDARD" # Single value arguments
-    "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_LIBRARIES" # Multi-value arguments
+    "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_LIBRARIES;FLAGS" # Multi-value arguments
     ${ARGN}
   )
   if(NOT LIBC_UNITTEST_SRCS)
@@ -86,7 +86,6 @@ function(add_libc_unittest target_name)
                         "'add_entrypoint_object' targets.")
   endif()
 
-  get_fq_target_name(${target_name} fq_target_name)
   get_fq_deps_list(fq_deps_list ${LIBC_UNITTEST_DEPENDS})
   get_object_files_for_test(
       link_object_files skipped_entrypoints_list ${fq_deps_list})
@@ -115,6 +114,15 @@ function(add_libc_unittest target_name)
     return()
   endif()
 
+  if(SHOW_INTERMEDIATE_OBJECTS)
+    message(STATUS "Adding unit test ${fq_target_name}")
+    if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+      foreach(dep IN LISTS ADD_OBJECT_DEPENDS)
+        message(STATUS "  ${fq_target_name} depends on ${dep}")
+      endforeach()
+    endif()
+  endif()
+
   add_executable(
     ${fq_target_name}
     EXCLUDE_FROM_ALL
@@ -138,13 +146,14 @@ function(add_libc_unittest target_name)
       PRIVATE ${LIBC_UNITTEST_COMPILE_OPTIONS}
     )
   endif()
-  if(LIBC_UNITTEST_CXX_STANDARD)
-    set_target_properties(
-      ${fq_target_name}
-      PROPERTIES
-        CXX_STANDARD ${LIBC_UNITTEST_CXX_STANDARD}
-    )
+  if(NOT LIBC_UNITTEST_CXX_STANDARD)
+    set(LIBC_UNITTEST_CXX_STANDARD ${CMAKE_CXX_STANDARD})
   endif()
+  set_target_properties(
+    ${fq_target_name}
+    PROPERTIES
+      CXX_STANDARD ${LIBC_UNITTEST_CXX_STANDARD}
+  )
 
   # Test object files will depend on LINK_LIBRARIES passed down from `add_fp_unittest`
   set(link_libraries ${link_object_files} ${LIBC_UNITTEST_LINK_LIBRARIES})
@@ -180,6 +189,100 @@ function(add_libc_unittest target_name)
       ${fq_target_name}
     )
   endif()
+endfunction(create_libc_unittest)
+
+# Internal function, used by `add_libc_unittest`.
+function(expand_flags_for_libc_unittest target_name flags)
+  cmake_parse_arguments(
+    "EXPAND_FLAGS"
+    "IGNORE_MARKER" # No Optional arguments
+    "" # No Single-value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  list(LENGTH flags nflags)
+  if(NOT ${nflags})
+    create_libc_unittest(
+      ${target_name}
+      DEPENDS "${EXPAND_FLAGS_DEPENDS}"
+      FLAGS "${EXPAND_FLAGS_FLAGS}"
+      "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
+    )
+    return()
+  endif()
+
+  list(POP_FRONT flags flag)
+  extract_flag_modifier(${flag} real_flag modifier)
+
+  if(NOT "${modifier}" STREQUAL "NO")
+    expand_flags_for_libc_unittest(
+      ${target_name}
+      "${flags}"
+      DEPENDS "${EXPAND_FLAGS_DEPENDS}" IGNORE_MARKER
+      FLAGS "${EXPAND_FLAGS_FLAGS}" IGNORE_MARKER
+      "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
+    )
+  endif()
+
+  if("${real_flag}" STREQUAL "" OR "${modifier}" STREQUAL "ONLY")
+    return()
+  endif()
+
+  set(NEW_FLAGS ${EXPAND_FLAGS_FLAGS})
+  list(REMOVE_ITEM NEW_FLAGS ${flag})
+  get_fq_dep_list_without_flag(NEW_DEPS ${real_flag} ${EXPAND_FLAGS_DEPENDS})
+
+  # Only target with `flag` has `.__NO_flag` target, `flag__NO` and
+  # `flag__ONLY` do not.
+  if(NOT "${modifier}")
+    set(TARGET_NAME "${target_name}.__NO_${flag}")
+  else()
+    set(TARGET_NAME "${target_name}")
+  endif()
+
+  expand_flags_for_libc_unittest(
+    ${TARGET_NAME}
+    "${flags}"
+    DEPENDS "${NEW_DEPS}" IGNORE_MARKER
+    FLAGS "${NEW_FLAGS}" IGNORE_MARKER
+    "${EXPAND_FLAGS_UNPARSED_ARGUMENTS}"
+  )
+endfunction(expand_flags_for_libc_unittest)
+
+function(add_libc_unittest target_name)
+  cmake_parse_arguments(
+    "ADD_TO_EXPAND"
+    "" # Optional arguments
+    "" # Single value arguments
+    "DEPENDS;FLAGS" # Multi-value arguments
+    ${ARGN}
+  )
+
+  get_fq_target_name(${target_name} fq_target_name)
+
+  if(ADD_TO_EXPAND_DEPENDS AND ("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS"))
+    message(STATUS "Gathering FLAGS from dependencies for ${fq_target_name}")
+  endif()
+
+  get_fq_deps_list(fq_deps_list ${ADD_TO_EXPAND_DEPENDS})
+  get_flags_from_dep_list(deps_flag_list ${fq_deps_list})
+  
+  list(APPEND ADD_TO_EXPAND_FLAGS ${deps_flag_list})
+  remove_duplicated_flags("${ADD_TO_EXPAND_FLAGS}" flags)
+  list(SORT flags)
+
+  if(SHOW_INTERMEDIATE_OBJECTS AND flags)
+    message(STATUS "Unit test ${fq_target_name} has FLAGS: ${flags}")
+  endif()
+
+  expand_flags_for_libc_unittest(
+    ${fq_target_name}
+    "${flags}"
+    DEPENDS ${fq_deps_list} IGNORE_MARKER
+    FLAGS ${flags} IGNORE_MARKER
+    ${ADD_TO_EXPAND_UNPARSED_ARGUMENTS}
+  )
 endfunction(add_libc_unittest)
 
 function(add_libc_testsuite suite_name)

diff  --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index 50ccc9e68b633..2895eba829dbe 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -21,8 +21,8 @@ function(add_fp_unittest name)
 
   add_libc_unittest(
     ${name}
-    "${MATH_UNITTEST_UNPARSED_ARGUMENTS}"
     LINK_LIBRARIES "${MATH_UNITTEST_LINK_LIBRARIES}"
+    "${MATH_UNITTEST_UNPARSED_ARGUMENTS}"
   )
 endfunction(add_fp_unittest)
 

diff  --git a/libc/test/src/__support/File/CMakeLists.txt b/libc/test/src/__support/File/CMakeLists.txt
index de8df1c0429e3..17ca25b7055d8 100644
--- a/libc/test/src/__support/File/CMakeLists.txt
+++ b/libc/test/src/__support/File/CMakeLists.txt
@@ -10,13 +10,13 @@ add_libc_unittest(
     libc_support_unittests
   SRCS
     file_test.cpp
+  LINK_LIBRARIES
+    LibcMemoryHelpers
   DEPENDS
     libc.include.errno
     libc.include.stdio
     libc.include.stdlib
     libc.src.__support.File.file
-  LINK_LIBRARIES
-    LibcMemoryHelpers
 )
 
 if (TARGET libc.src.__support.File.platform_file)

diff  --git a/libc/test/src/__support/OSUtil/linux/x86_64/CMakeLists.txt b/libc/test/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
index 63e33baaf1635..e0f2549bd8de2 100644
--- a/libc/test/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
+++ b/libc/test/src/__support/OSUtil/linux/x86_64/CMakeLists.txt
@@ -2,8 +2,8 @@ add_libc_unittest(
   syscall_unittest
   SUITE libc_osutil_tests
   SRCS syscall_test.cpp
-  DEPENDS
-    libc.src.__support.OSUtil.osutil
   COMPILE_OPTIONS
     -Wno-unused-variable # Only signature tests, declared variables are unused.
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
 )

diff  --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index f985dab25bf89..b91f3c213a224 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -175,13 +175,13 @@ add_fp_unittest(
     libc_math_exhaustive_tests
   SRCS
     hypotf_test.cpp
+  COMPILE_OPTIONS
+    -O3
   DEPENDS
     .exhaustive_test
     libc.include.math
     libc.src.math.hypotf
     libc.src.__support.FPUtil.fputil
-  COMPILE_OPTIONS
-    -O3
   LINK_LIBRARIES
     -lpthread
 )

diff  --git a/libc/test/src/stdio/printf_core/CMakeLists.txt b/libc/test/src/stdio/printf_core/CMakeLists.txt
index 692a39621534d..3b38f2ccdb1a7 100644
--- a/libc/test/src/stdio/printf_core/CMakeLists.txt
+++ b/libc/test/src/stdio/printf_core/CMakeLists.txt
@@ -4,12 +4,12 @@ add_libc_unittest(
     libc_stdio_unittests
   SRCS
     parser_test.cpp
+  LINK_LIBRARIES
+    LibcPrintfHelpers
   DEPENDS
     libc.src.stdio.printf_core.parser
     libc.src.stdio.printf_core.core_structs
     libc.src.__support.arg_list
-  LINK_LIBRARIES
-    LibcPrintfHelpers
 )
 
 add_libc_unittest(

diff  --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt
index e60f9ab3d3994..6e4c227ce374e 100644
--- a/libc/test/src/string/CMakeLists.txt
+++ b/libc/test/src/string/CMakeLists.txt
@@ -275,13 +275,13 @@ function(add_libc_multi_impl_test name)
         ${fq_config_name}_test
         SUITE
           libc_string_unittests
-        DEPENDS
-          ${fq_config_name}
         COMPILE_OPTIONS
           ${LIBC_COMPILE_OPTIONS_NATIVE}
         LINK_LIBRARIES
           LibcMemoryHelpers
         ${ARGN}
+        DEPENDS
+          ${fq_config_name}
       )
       get_fq_target_name(${fq_config_name}_test fq_target_name)
     else()

diff  --git a/libc/test/src/string/memory_utils/CMakeLists.txt b/libc/test/src/string/memory_utils/CMakeLists.txt
index 5705190c45e9b..7836076121dd9 100644
--- a/libc/test/src/string/memory_utils/CMakeLists.txt
+++ b/libc/test/src/string/memory_utils/CMakeLists.txt
@@ -6,11 +6,11 @@ add_libc_unittest(
     elements_test.cpp
     memory_access_test.cpp
     utils_test.cpp
+  COMPILE_OPTIONS
+    ${LIBC_COMPILE_OPTIONS_NATIVE}
+    -ffreestanding
   DEPENDS
     libc.src.string.memory_utils.memory_utils
     libc.src.__support.CPP.array
     libc.src.__support.CPP.array_ref
-  COMPILE_OPTIONS
-    ${LIBC_COMPILE_OPTIONS_NATIVE}
-    -ffreestanding
 )


        


More information about the libc-commits mailing list