[clang] [llvm] [mlir] [CMake] Add dependent project mode for Flang's MLIR (PR #221724)

Mehdi Amini via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 8 01:11:48 PDT 2026


https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/221724

>From 89bacd29aa517595bf48440cb1f5a1de7f63b6b0 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Mon, 7 Sep 2026 06:11:56 -0700
Subject: [PATCH] [CMake] Infer dependency-only projects from the cache

LLVM_ENABLE_PROJECTS historically treats projects enabled to satisfy another
project's dependency the same as projects selected by the user. Consequently,
implicit projects attach their complete build, install, and test suites to
LLVM's aggregate targets.

Keep the cache entry as the user-requested project roots and use the normal
LLVM_ENABLE_PROJECTS variable as the effective dependency closure. Projects in
the effective list but not the cache entry are configured with EXCLUDE_FROM_ALL.
Normalize the special all value before comparing the two sets.

This makes Flang's MLIR and Clang dependencies dependency-only without a second
project collection. It also applies the same rule to Clang when it is added for
LLDB. Forward the cached roots to cross-compilation and bootstrap configurations
so implicit projects do not become explicit in nested builds.

Let MLIR own its dependency-only test policy: configure test support libraries
for downstream consumers without creating MLIR unit tests or registering its
lit suite. Explicitly enabling MLIR preserves the existing behavior.

Validation:
- Configured Flang with implicit MLIR test support.
- Configured Flang and MLIR explicitly with tests enabled.
- Configured LLVM_ENABLE_PROJECTS=all with tests disabled.
- Verified implicit mode exposes check-flang but no MLIR test-suite targets.
- Verified explicit mode retains check-mlir and MLIRUnitTests.

Assisted-by: Codex
---
 clang/CMakeLists.txt                  |  5 ++++-
 llvm/CMakeLists.txt                   | 22 ++++++++++++++++++----
 llvm/cmake/modules/AddLLVM.cmake      | 14 ++++++++++++--
 llvm/cmake/modules/CrossCompile.cmake |  2 +-
 mlir/CMakeLists.txt                   | 24 ++++++++++++++++++------
 5 files changed, 53 insertions(+), 14 deletions(-)

diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index fc71cf45dbb34..6977458da67e9 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -851,7 +851,10 @@ if (CLANG_ENABLE_BOOTSTRAP)
   # Populate the passthrough variables
   foreach(variableName ${CLANG_BOOTSTRAP_PASSTHROUGH} ${_BOOTSTRAP_DEFAULT_PASSTHROUGH})
     if(DEFINED ${variableName})
-      if("${${variableName}}" STREQUAL "")
+      if(variableName STREQUAL "LLVM_ENABLE_PROJECTS" AND
+         DEFINED CACHE{LLVM_ENABLE_PROJECTS})
+        string(REPLACE ";" "|" value "$CACHE{LLVM_ENABLE_PROJECTS}")
+      elseif("${${variableName}}" STREQUAL "")
         set(value "")
       else()
         string(REPLACE ";" "|" value "${${variableName}}")
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 44299d51d784a..b4a99a60b97a5 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -270,6 +270,15 @@ if(LIBOMP_ENABLE_ARM64X)
   set(RUNTIMES_arm64ec-pc-windows-msvc_LIBOMP_ENABLE_ARM64X ON)
 endif()
 
+list(REMOVE_DUPLICATES LLVM_ENABLE_PROJECTS)
+
+# The cache entry contains the projects explicitly requested by the user, while
+# LLVM_ENABLE_PROJECTS may also contain projects added to satisfy dependencies.
+set(llvm_explicit_projects "$CACHE{LLVM_ENABLE_PROJECTS}")
+if(llvm_explicit_projects STREQUAL "all")
+  set(llvm_explicit_projects ${LLVM_ALL_PROJECTS})
+endif()
+
 # LLVM_ENABLE_PROJECTS_USED is `ON` if the user has ever used the
 # `LLVM_ENABLE_PROJECTS` CMake cache variable.  This exists for
 # several reasons:
@@ -293,7 +302,11 @@ if (LLVM_ENABLE_PROJECTS_USED OR NOT LLVM_ENABLE_PROJECTS STREQUAL "")
     string(TOUPPER "${proj}" upper_proj)
     string(REGEX REPLACE "-" "_" upper_proj ${upper_proj})
     if ("${proj}" IN_LIST LLVM_ENABLE_PROJECTS)
-      message(STATUS "${proj} project is enabled")
+      if ("${proj}" IN_LIST llvm_explicit_projects)
+        message(STATUS "${proj} project is enabled")
+      else()
+        message(STATUS "${proj} project is enabled as a dependency")
+      endif()
       set(SHOULD_ENABLE_PROJECT TRUE)
       set(PROJ_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../${proj}")
       if(NOT EXISTS "${PROJ_DIR}" OR NOT IS_DIRECTORY "${PROJ_DIR}")
@@ -312,9 +325,9 @@ if (LLVM_ENABLE_PROJECTS_USED OR NOT LLVM_ENABLE_PROJECTS STREQUAL "")
       set(SHOULD_ENABLE_PROJECT FALSE)
     endif()
     # Force `LLVM_TOOL_${upper_proj}_BUILD` variables to have values that
-    # corresponds with `LLVM_ENABLE_PROJECTS`. This prevents the user setting
-    # `LLVM_TOOL_${upper_proj}_BUILD` variables externally. At some point
-    # we should deprecate allowing users to set these variables by turning them
+    # correspond with `LLVM_ENABLE_PROJECTS`. This prevents the user setting
+    # `LLVM_TOOL_${upper_proj}_BUILD` variables externally. At some point we
+    # should deprecate allowing users to set these variables by turning them
     # into normal CMake variables rather than cache variables.
     set(LLVM_TOOL_${upper_proj}_BUILD
       ${SHOULD_ENABLE_PROJECT}
@@ -324,6 +337,7 @@ if (LLVM_ENABLE_PROJECTS_USED OR NOT LLVM_ENABLE_PROJECTS STREQUAL "")
   endforeach()
 endif()
 unset(SHOULD_ENABLE_PROJECT)
+unset(llvm_explicit_projects)
 
 # Build llvm with ccache if the package is present
 set(LLVM_CCACHE_BUILD OFF CACHE BOOL "Set to ON for a ccache enabled build")
diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index a267166eb6c2d..a35027cb9b884 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -1762,6 +1762,14 @@ function(add_llvm_subdirectory project type name)
   if("${add_llvm_external_dir}" STREQUAL "")
     set(add_llvm_external_dir ${name})
   endif()
+  set(llvm_explicit_projects "$CACHE{LLVM_ENABLE_PROJECTS}")
+  if(llvm_explicit_projects STREQUAL "all")
+    set(llvm_explicit_projects ${LLVM_ALL_PROJECTS})
+  endif()
+  if("${name}" IN_LIST LLVM_ENABLE_PROJECTS AND
+     NOT "${name}" IN_LIST llvm_explicit_projects)
+    set(exclude_from_all EXCLUDE_FROM_ALL)
+  endif()
   canonicalize_tool_name(${name} nameUPPER)
   set(canonical_full_name ${project}_${type}_${nameUPPER})
   get_property(already_processed GLOBAL PROPERTY ${canonical_full_name}_PROCESSED)
@@ -1776,7 +1784,8 @@ function(add_llvm_subdirectory project type name)
            "Whether to build ${name} as part of ${project}" On)
     mark_as_advanced(${project}_${type}_${name}_BUILD)
     if(${canonical_full_name}_BUILD)
-      add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir} ${add_llvm_external_dir})
+      add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}
+                       ${add_llvm_external_dir} ${exclude_from_all})
     endif()
   else()
     set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR
@@ -1794,7 +1803,8 @@ function(add_llvm_subdirectory project type name)
       ${${canonical_full_name}_BUILD_DEFAULT})
     if (${canonical_full_name}_BUILD)
       if(EXISTS ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR})
-        add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir})
+        add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}
+                         ${add_llvm_external_dir} ${exclude_from_all})
       elseif(NOT "${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}" STREQUAL "")
         message(WARNING "Nonexistent directory for ${name}: ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}")
       endif()
diff --git a/llvm/cmake/modules/CrossCompile.cmake b/llvm/cmake/modules/CrossCompile.cmake
index 28fb430dc98e1..153d77e454d47 100644
--- a/llvm/cmake/modules/CrossCompile.cmake
+++ b/llvm/cmake/modules/CrossCompile.cmake
@@ -67,7 +67,7 @@ function(llvm_create_cross_target project_name target_name toolchain buildtype)
          "${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD}")
 
   string(REPLACE ";" "$<SEMICOLON>" llvm_enable_projects_arg
-         "${LLVM_ENABLE_PROJECTS}")
+         "$CACHE{LLVM_ENABLE_PROJECTS}")
   string(REPLACE ";" "$<SEMICOLON>" llvm_external_projects_arg
          "${LLVM_EXTERNAL_PROJECTS}")
   string(REPLACE ";" "$<SEMICOLON>" llvm_enable_runtimes_arg
diff --git a/mlir/CMakeLists.txt b/mlir/CMakeLists.txt
index 7bedfe09e798a..8b4069dd42185 100644
--- a/mlir/CMakeLists.txt
+++ b/mlir/CMakeLists.txt
@@ -263,14 +263,26 @@ add_subdirectory(lib/CAPI)
 
 if (MLIR_INCLUDE_TESTS)
   add_definitions(-DMLIR_INCLUDE_TESTS)
-  add_custom_target(MLIRUnitTests)
-  set_target_properties(MLIRUnitTests PROPERTIES FOLDER "MLIR/Tests")
-  if (TARGET llvm_gtest)
-    add_subdirectory(unittests)
+  set(mlir_explicit_projects "$CACHE{LLVM_ENABLE_PROJECTS}")
+  if(mlir_explicit_projects STREQUAL "all")
+    set(mlir_explicit_projects ${LLVM_ALL_PROJECTS})
+  endif()
+  if ("mlir" IN_LIST LLVM_ENABLE_PROJECTS AND
+      NOT "mlir" IN_LIST mlir_explicit_projects)
+    # Make test support libraries available to dependent projects without
+    # registering MLIR's own unit and regression tests with check-all.
+    add_subdirectory(test/lib)
   else()
-    message(WARNING "gtest not found, unittests will not be available")
+    add_custom_target(MLIRUnitTests)
+    set_target_properties(MLIRUnitTests PROPERTIES FOLDER "MLIR/Tests")
+    if (TARGET llvm_gtest)
+      add_subdirectory(unittests)
+    else()
+      message(WARNING "gtest not found, unittests will not be available")
+    endif()
+    add_subdirectory(test)
   endif()
-  add_subdirectory(test)
+  unset(mlir_explicit_projects)
 endif()
 # Tools needs to come late to ensure that MLIR_ALL_LIBS is populated.
 # Generally things after this point may depend on MLIR_ALL_LIBS or libMLIR.so.



More information about the cfe-commits mailing list