This is an automated email from the ASF dual-hosted git repository.

raulcd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new bc51a762141 GH-48091: [C++] Use FetchContent for bundled c-ares 
(#48092)
bc51a762141 is described below

commit bc51a7621419272cb847b1c6da160959c1934cf3
Author: Raúl Cumplido <[email protected]>
AuthorDate: Wed Nov 19 14:11:18 2025 +0100

    GH-48091: [C++] Use FetchContent for bundled c-ares (#48092)
    
    ### Rationale for this change
    
    As a follow up of requiring a minimum CMake version >= 3.25 we discussed 
moving our dependencies from ExternalProject to FetchContent. This can heavily 
simplify our third party dependency management. Moving c-ares is the next step 
before moving grpc.
    
    ### What changes are included in this PR?
    
    The general change is moving from `ExternalProject` to `FetchContent`.
    
    It also add some required integration due to other dependencies, like grpc, 
using `ExternalProject`. We not only have to build but also install in order 
for those other dependencies to find c-ares. This causes some timing issues 
between config, build, install that requires us to create a custom target to 
depend on so the other dependencies find abseil.
    
    ### Are these changes tested?
    
    Yes, the changes are tested locally and on CI.
    
    ### Are there any user-facing changes?
    
    No
    * GitHub Issue: #48091
    
    Authored-by: Raúl Cumplido <[email protected]>
    Signed-off-by: Raúl Cumplido <[email protected]>
---
 cpp/cmake_modules/ThirdpartyToolchain.cmake | 107 ++++++++++++++++++++--------
 1 file changed, 76 insertions(+), 31 deletions(-)

diff --git a/cpp/cmake_modules/ThirdpartyToolchain.cmake 
b/cpp/cmake_modules/ThirdpartyToolchain.cmake
index 910f256c81e..835baec87ba 100644
--- a/cpp/cmake_modules/ThirdpartyToolchain.cmake
+++ b/cpp/cmake_modules/ThirdpartyToolchain.cmake
@@ -2950,33 +2950,67 @@ if(ARROW_WITH_UTF8PROC)
   resolve_dependency(${utf8proc_resolve_dependency_args})
 endif()
 
-macro(build_cares)
-  message(STATUS "Building c-ares from source")
-  set(CARES_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/cares_ep-install")
-  set(CARES_INCLUDE_DIR "${CARES_PREFIX}/include")
-
-  # If you set -DCARES_SHARED=ON then the build system names the library
-  # libcares_static.a
-  set(CARES_STATIC_LIB
-      
"${CARES_PREFIX}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}cares${CMAKE_STATIC_LIBRARY_SUFFIX}"
-  )
+function(build_cares)
+  list(APPEND CMAKE_MESSAGE_INDENT "c-ares: ")
+  message(STATUS "Building c-ares from source using FetchContent")
+  set(CARES_VENDORED
+      TRUE
+      PARENT_SCOPE)
+  set(CARES_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/cares_fc-install")
+  set(CARES_PREFIX
+      "${CARES_PREFIX}"
+      PARENT_SCOPE)
 
-  set(CARES_CMAKE_ARGS "${EP_COMMON_CMAKE_ARGS}" 
"-DCMAKE_INSTALL_PREFIX=${CARES_PREFIX}"
-                       -DCARES_SHARED=OFF -DCARES_STATIC=ON)
+  fetchcontent_declare(cares
+                       URL ${CARES_SOURCE_URL}
+                       URL_HASH "SHA256=${ARROW_CARES_BUILD_SHA256_CHECKSUM}")
 
-  externalproject_add(cares_ep
-                      ${EP_COMMON_OPTIONS}
-                      URL ${CARES_SOURCE_URL}
-                      URL_HASH "SHA256=${ARROW_CARES_BUILD_SHA256_CHECKSUM}"
-                      CMAKE_ARGS ${CARES_CMAKE_ARGS}
-                      BUILD_BYPRODUCTS "${CARES_STATIC_LIB}")
+  prepare_fetchcontent()
 
-  file(MAKE_DIRECTORY ${CARES_INCLUDE_DIR})
+  set(CARES_SHARED OFF)
+  set(CARES_STATIC ON)
+  set(CARES_INSTALL ON)
+  set(CARES_BUILD_TOOLS OFF)
+  set(CARES_BUILD_TESTS OFF)
+  fetchcontent_makeavailable(cares)
+
+  # gRPC requires c-ares to be installed to a known location.
+  # We have to do this in two steps to avoid double installation of c-ares
+  # when Arrow is installed.
+  # This custom target ensures c-ares is built before we install
+  add_custom_target(cares_built DEPENDS c-ares::cares)
+
+  # Disable c-ares's install script after it's built to prevent double 
installation
+  add_custom_command(OUTPUT "${cares_BINARY_DIR}/cmake_install.cmake.saved"
+                     COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                             "${cares_BINARY_DIR}/cmake_install.cmake"
+                             "${cares_BINARY_DIR}/cmake_install.cmake.saved"
+                     COMMAND ${CMAKE_COMMAND} -E echo
+                             "# c-ares install disabled to prevent double 
installation with Arrow"
+                             > "${cares_BINARY_DIR}/cmake_install.cmake"
+                     DEPENDS cares_built
+                     COMMENT "Disabling c-ares install to prevent double 
installation"
+                     VERBATIM)
+
+  add_custom_target(cares_install_disabled ALL
+                    DEPENDS "${cares_BINARY_DIR}/cmake_install.cmake.saved")
+
+  # Install c-ares to CARES_PREFIX for gRPC to find
+  add_custom_command(OUTPUT "${CARES_PREFIX}/.cares_installed"
+                     COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                             "${cares_BINARY_DIR}/cmake_install.cmake.saved"
+                             "${cares_BINARY_DIR}/cmake_install.cmake.tmp"
+                     COMMAND ${CMAKE_COMMAND} 
-DCMAKE_INSTALL_PREFIX=${CARES_PREFIX}
+                             -DCMAKE_INSTALL_CONFIG_NAME=$<CONFIG> -P
+                             "${cares_BINARY_DIR}/cmake_install.cmake.tmp" ||
+                             ${CMAKE_COMMAND} -E true
+                     COMMAND ${CMAKE_COMMAND} -E touch 
"${CARES_PREFIX}/.cares_installed"
+                     DEPENDS cares_install_disabled
+                     COMMENT "Installing c-ares to ${CARES_PREFIX} for gRPC"
+                     VERBATIM)
 
-  add_library(c-ares::cares STATIC IMPORTED)
-  set_target_properties(c-ares::cares PROPERTIES IMPORTED_LOCATION 
"${CARES_STATIC_LIB}")
-  target_include_directories(c-ares::cares BEFORE INTERFACE 
"${CARES_INCLUDE_DIR}")
-  add_dependencies(c-ares::cares cares_ep)
+  # Make cares_fc depend on the install completion marker
+  add_custom_target(cares_fc DEPENDS "${CARES_PREFIX}/.cares_installed")
 
   if(APPLE)
     # libresolv must be linked from c-ares version 1.16.1
@@ -2985,10 +3019,11 @@ macro(build_cares)
                                                    "${LIBRESOLV_LIBRARY}")
   endif()
 
-  set(CARES_VENDORED TRUE)
-
-  list(APPEND ARROW_BUNDLED_STATIC_LIBS c-ares::cares)
-endmacro()
+  set(ARROW_BUNDLED_STATIC_LIBS
+      ${ARROW_BUNDLED_STATIC_LIBS} c-ares::cares
+      PARENT_SCOPE)
+  list(POP_BACK CMAKE_MESSAGE_INDENT)
+endfunction()
 
 # ----------------------------------------------------------------------
 # Dependencies for Arrow Flight RPC
@@ -3136,7 +3171,9 @@ function(build_absl)
     # This is due to upstream absl::cctz issue
     # https://github.com/abseil/abseil-cpp/issues/283
     find_library(CoreFoundation CoreFoundation)
-    set_property(TARGET absl::time
+    # When ABSL_ENABLE_INSTALL is ON, the real target is "time" not "absl_time"
+    # Cannot use set_property on alias targets (absl::time is an alias)
+    set_property(TARGET time
                  APPEND
                  PROPERTY INTERFACE_LINK_LIBRARIES ${CoreFoundation})
   endif()
@@ -3189,7 +3226,7 @@ macro(build_grpc)
     add_dependencies(grpc_dependencies absl_fc)
   endif()
   if(CARES_VENDORED)
-    add_dependencies(grpc_dependencies cares_ep)
+    add_dependencies(grpc_dependencies cares_fc)
   endif()
 
   if(GFLAGS_VENDORED)
@@ -3208,8 +3245,16 @@ macro(build_grpc)
   get_filename_component(GRPC_PB_ROOT "${GRPC_PROTOBUF_INCLUDE_DIR}" DIRECTORY)
   get_target_property(GRPC_Protobuf_PROTOC_LIBRARY ${ARROW_PROTOBUF_LIBPROTOC}
                       IMPORTED_LOCATION)
-  get_target_property(GRPC_CARES_INCLUDE_DIR c-ares::cares 
INTERFACE_INCLUDE_DIRECTORIES)
-  get_filename_component(GRPC_CARES_ROOT "${GRPC_CARES_INCLUDE_DIR}" DIRECTORY)
+
+  # For FetchContent c-ares, use the install prefix directly
+  if(CARES_VENDORED)
+    set(GRPC_CARES_ROOT "${CARES_PREFIX}")
+  else()
+    get_target_property(GRPC_CARES_INCLUDE_DIR c-ares::cares
+                        INTERFACE_INCLUDE_DIRECTORIES)
+    get_filename_component(GRPC_CARES_ROOT "${GRPC_CARES_INCLUDE_DIR}" 
DIRECTORY)
+  endif()
+
   get_target_property(GRPC_RE2_INCLUDE_DIR re2::re2 
INTERFACE_INCLUDE_DIRECTORIES)
   get_filename_component(GRPC_RE2_ROOT "${GRPC_RE2_INCLUDE_DIR}" DIRECTORY)
 

Reply via email to