@@ -1867,83 +1867,123 @@ endif()
18671867# ----------------------------------------------------------------------
18681868# Protocol Buffers (required for ORC, Flight and Substrait libraries)
18691869
1870- macro (build_protobuf)
1871- message (STATUS "Building Protocol Buffers from source" )
1872- set (PROTOBUF_VENDORED TRUE )
1873- set (PROTOBUF_PREFIX "${CMAKE_CURRENT_BINARY_DIR} /protobuf_ep-install" )
1870+ function (build_protobuf)
1871+ list (APPEND CMAKE_MESSAGE_INDENT "PROTOBUF: " )
1872+ message (STATUS "Building Protocol Buffers from source using FetchContent" )
1873+ set (PROTOBUF_VENDORED
1874+ TRUE
1875+ PARENT_SCOPE)
1876+ set (PROTOBUF_PREFIX "${CMAKE_CURRENT_BINARY_DIR} /protobuf_fc-install" )
1877+ set (PROTOBUF_PREFIX
1878+ "${PROTOBUF_PREFIX} "
1879+ PARENT_SCOPE)
18741880 set (PROTOBUF_INCLUDE_DIR "${PROTOBUF_PREFIX} /include" )
1881+ set (PROTOBUF_INCLUDE_DIR
1882+ "${PROTOBUF_INCLUDE_DIR} "
1883+ PARENT_SCOPE)
1884+
1885+ fetchcontent_declare(protobuf
1886+ URL ${PROTOBUF_SOURCE_URL}
1887+ URL_HASH "SHA256=${ARROW_PROTOBUF_BUILD_SHA256_CHECKSUM} "
1888+ SOURCE_SUBDIR cmake)
1889+
1890+ prepare_fetchcontent()
1891+ # Configure Protobuf options before FetchContent
1892+
18751893 # This flag is based on what the user initially requested but if
18761894 # we've fallen back to building protobuf we always build it statically
18771895 # so we need to reset the flag so that we can link against it correctly
18781896 # later.
18791897 set (Protobuf_USE_STATIC_LIBS ON )
1880- # Newer protobuf releases always have a lib prefix independent from CMAKE_STATIC_LIBRARY_PREFIX
1881- set (PROTOBUF_STATIC_LIB
1882- "${PROTOBUF_PREFIX} /lib/libprotobuf${CMAKE_STATIC_LIBRARY_SUFFIX} " )
1883- set (PROTOC_STATIC_LIB "${PROTOBUF_PREFIX} /lib/libprotoc${CMAKE_STATIC_LIBRARY_SUFFIX} " )
1884- set (Protobuf_PROTOC_LIBRARY "${PROTOC_STATIC_LIB} " )
1885- set (PROTOBUF_COMPILER "${PROTOBUF_PREFIX} /bin/protoc" )
18861898
18871899 # Strip lto flags (which may be added by dh_auto_configure)
18881900 # See https://github.com/protocolbuffers/protobuf/issues/7092
1889- set (PROTOBUF_C_FLAGS ${EP_C_FLAGS} )
1890- set (PROTOBUF_CXX_FLAGS ${EP_CXX_FLAGS} )
1891- string (REPLACE "-flto=auto" "" PROTOBUF_C_FLAGS "${PROTOBUF_C_FLAGS} " )
1892- string (REPLACE "-ffat-lto-objects" "" PROTOBUF_C_FLAGS "${PROTOBUF_C_FLAGS} " )
1893- string (REPLACE "-flto=auto" "" PROTOBUF_CXX_FLAGS "${PROTOBUF_CXX_FLAGS} " )
1894- string (REPLACE "-ffat-lto-objects" "" PROTOBUF_CXX_FLAGS "${PROTOBUF_CXX_FLAGS} " )
1895- set (PROTOBUF_CMAKE_ARGS
1896- ${EP_COMMON_CMAKE_ARGS}
1897- "-DCMAKE_CXX_FLAGS=${PROTOBUF_CXX_FLAGS} "
1898- "-DCMAKE_C_FLAGS=${PROTOBUF_C_FLAGS} "
1899- "-DCMAKE_INSTALL_PREFIX=${PROTOBUF_PREFIX} "
1900- -Dprotobuf_BUILD_TESTS=OFF
1901- -Dprotobuf_DEBUG_POSTFIX =)
1901+ string (REPLACE "-flto=auto" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS} " )
1902+ string (REPLACE "-ffat-lto-objects" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS} " )
1903+ string (REPLACE "-flto=auto" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} " )
1904+ string (REPLACE "-ffat-lto-objects" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} " )
1905+
1906+ set (protobuf_BUILD_TESTS OFF )
19021907 if (MSVC AND NOT ARROW_USE_STATIC_CRT)
1903- list (APPEND PROTOBUF_CMAKE_ARGS "-Dprotobuf_MSVC_STATIC_RUNTIME=OFF" )
1904- endif ()
1905- if (ZLIB_ROOT)
1906- list (APPEND PROTOBUF_CMAKE_ARGS "-DZLIB_ROOT=${ZLIB_ROOT} " )
1908+ set (protobuf_MSVC_STATIC_RUNTIME OFF )
19071909 endif ()
1908- set (PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS CMAKE_ARGS ${PROTOBUF_CMAKE_ARGS} SOURCE_SUBDIR
1909- "cmake" )
19101910
1911- externalproject_add(protobuf_ep
1912- ${EP_COMMON_OPTIONS} ${PROTOBUF_EXTERNAL_PROJECT_ADD_ARGS}
1913- BUILD_BYPRODUCTS "${PROTOBUF_STATIC_LIB} " "${PROTOBUF_COMPILER} "
1914- BUILD_IN_SOURCE 1
1915- URL ${PROTOBUF_SOURCE_URL}
1916- URL_HASH "SHA256=${ARROW_PROTOBUF_BUILD_SHA256_CHECKSUM} " )
1911+ fetchcontent_makeavailable(protobuf)
19171912
1918- file (MAKE_DIRECTORY "${PROTOBUF_INCLUDE_DIR} " )
1913+ # Get the actual include directory from the protobuf target
1914+ # For FetchContent, this points to the source directory which contains the .proto files
1915+ set (PROTOBUF_INCLUDE_DIR "${protobuf_SOURCE_DIR} /src" )
19191916 # For compatibility of CMake's FindProtobuf.cmake.
19201917 set (Protobuf_INCLUDE_DIRS "${PROTOBUF_INCLUDE_DIR} " )
1918+ set (Protobuf_INCLUDE_DIRS
1919+ "${Protobuf_INCLUDE_DIRS} "
1920+ PARENT_SCOPE)
1921+ # Set import dirs so protoc can find well-known types like timestamp.proto
1922+ set (Protobuf_IMPORT_DIRS "${PROTOBUF_INCLUDE_DIR} " )
1923+ set (Protobuf_IMPORT_DIRS
1924+ "${Protobuf_IMPORT_DIRS} "
1925+ PARENT_SCOPE)
1926+
1927+ # For FetchContent builds, protoc and libprotoc are regular targets, not imported
1928+ # We can't get their locations at configure time, so we set placeholders
1929+ # The actual locations will be resolved at build time or by the install step
1930+ set (PROTOBUF_COMPILER "$<TARGET_FILE:protobuf::protoc>" )
1931+ set (PROTOC_STATIC_LIB "$<TARGET_FILE:protobuf::libprotoc>" )
1932+ set (Protobuf_PROTOC_LIBRARY "${PROTOC_STATIC_LIB} " )
1933+
1934+ # gRPC requires Protobuf to be installed to a known location.
1935+ # We have to do this in two steps to avoid double installation of Protobuf
1936+ # when Arrow is installed.
1937+ # This custom target ensures Protobuf is built before we install
1938+ # TODO: Investigate if libprotobuf-lite is actually needed by Arrow/gRPC
1939+ add_custom_target (protobuf_built
1940+ DEPENDS protobuf::libprotobuf protobuf::libprotobuf-lite
1941+ protobuf::libprotoc protobuf::protoc)
1942+
1943+ # Disable Protobuf's install script after it's built to prevent double installation
1944+ add_custom_command (OUTPUT "${protobuf_BINARY_DIR} /cmake_install.cmake.saved"
1945+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
1946+ "${protobuf_BINARY_DIR} /cmake_install.cmake"
1947+ "${protobuf_BINARY_DIR} /cmake_install.cmake.saved"
1948+ COMMAND ${CMAKE_COMMAND} -E echo
1949+ "# Protobuf install disabled to prevent double installation with Arrow"
1950+ > "${protobuf_BINARY_DIR} /cmake_install.cmake"
1951+ DEPENDS protobuf_built
1952+ COMMENT "Disabling Protobuf install to prevent double installation"
1953+ VERBATIM )
1954+
1955+ add_custom_target (protobuf_install_disabled ALL
1956+ DEPENDS "${protobuf_BINARY_DIR} /cmake_install.cmake.saved" )
1957+
1958+ # Install Protobuf to PROTOBUF_PREFIX for gRPC to find
1959+ add_custom_command (OUTPUT "${PROTOBUF_PREFIX} /.protobuf_installed"
1960+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
1961+ "${protobuf_BINARY_DIR} /cmake_install.cmake.saved"
1962+ "${protobuf_BINARY_DIR} /cmake_install.cmake.tmp"
1963+ COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${PROTOBUF_PREFIX}
1964+ -DCMAKE_INSTALL_CONFIG_NAME=$<CONFIG> -P
1965+ "${protobuf_BINARY_DIR} /cmake_install.cmake.tmp" ||
1966+ ${CMAKE_COMMAND} -E true
1967+ COMMAND ${CMAKE_COMMAND} -E touch
1968+ "${PROTOBUF_PREFIX} /.protobuf_installed"
1969+ DEPENDS protobuf_install_disabled
1970+ COMMENT "Installing Protobuf to ${PROTOBUF_PREFIX} for gRPC"
1971+ VERBATIM )
1972+
1973+ # Make protobuf_fc depend on the install completion marker
1974+ add_custom_target (protobuf_fc DEPENDS "${PROTOBUF_PREFIX} /.protobuf_installed" )
1975+
1976+ # For FetchContent, we don't create arrow::protobuf::* aliases because
1977+ # protobuf::* are themselves aliases and CMake doesn't allow alias-to-alias.
1978+ # The code in resolve_dependency below will use protobuf::* targets directly.
19211979
1922- add_library (arrow::protobuf::libprotobuf STATIC IMPORTED )
1923- set_target_properties (arrow::protobuf::libprotobuf PROPERTIES IMPORTED_LOCATION
1924- "${PROTOBUF_STATIC_LIB} " )
1925- target_include_directories (arrow::protobuf::libprotobuf BEFORE
1926- INTERFACE "${PROTOBUF_INCLUDE_DIR} " )
1927- add_library (arrow::protobuf::libprotoc STATIC IMPORTED )
1928- set_target_properties (arrow::protobuf::libprotoc PROPERTIES IMPORTED_LOCATION
1929- "${PROTOC_STATIC_LIB} " )
1930- target_include_directories (arrow::protobuf::libprotoc BEFORE
1931- INTERFACE "${PROTOBUF_INCLUDE_DIR} " )
1932- add_executable (arrow::protobuf::protoc IMPORTED )
1933- set_target_properties (arrow::protobuf::protoc PROPERTIES IMPORTED_LOCATION
1934- "${PROTOBUF_COMPILER} " )
1935-
1936- add_dependencies (arrow::protobuf::libprotobuf protobuf_ep)
1937- add_dependencies (arrow::protobuf::protoc protobuf_ep)
1938-
1939- list (APPEND ARROW_BUNDLED_STATIC_LIBS arrow::protobuf::libprotobuf)
1980+ list (APPEND ARROW_BUNDLED_STATIC_LIBS protobuf::libprotobuf)
19401981
19411982 if (CMAKE_CROSSCOMPILING )
19421983 # If we are cross compiling, we need to build protoc for the host
19431984 # system also, as it is used when building Arrow
1944- # We do this by calling CMake as a child process
1945- # with CXXFLAGS / CFLAGS and CMake flags cleared.
1946- set (PROTOBUF_HOST_PREFIX "${CMAKE_CURRENT_BINARY_DIR} /protobuf_ep_host-install" )
1985+ # We reuse the FetchContent downloaded source but build it with host compiler
1986+ set (PROTOBUF_HOST_PREFIX "${CMAKE_CURRENT_BINARY_DIR} /protobuf_fc_host-install" )
19471987 set (PROTOBUF_HOST_COMPILER "${PROTOBUF_HOST_PREFIX} /bin/protoc" )
19481988
19491989 set (PROTOBUF_HOST_CMAKE_ARGS
@@ -1953,21 +1993,23 @@ macro(build_protobuf)
19531993 -Dprotobuf_BUILD_TESTS=OFF
19541994 -Dprotobuf_DEBUG_POSTFIX =)
19551995
1956- externalproject_add(protobuf_ep_host
1996+ # Use the already-downloaded FetchContent source directory
1997+ externalproject_add(protobuf_fc_host
19571998 ${EP_COMMON_OPTIONS}
19581999 CMAKE_ARGS ${PROTOBUF_HOST_CMAKE_ARGS}
2000+ SOURCE_DIR "${protobuf_SOURCE_DIR} "
2001+ SOURCE_SUBDIR cmake
19592002 BUILD_BYPRODUCTS "${PROTOBUF_HOST_COMPILER} "
1960- BUILD_IN_SOURCE 1
1961- URL ${PROTOBUF_SOURCE_URL}
1962- URL_HASH "SHA256=${ARROW_PROTOBUF_BUILD_SHA256_CHECKSUM} " )
2003+ DOWNLOAD_COMMAND "" DOWNLOAD_EXTRACT_TIMESTAMP TRUE )
19632004
19642005 add_executable (arrow::protobuf::host_protoc IMPORTED )
19652006 set_target_properties (arrow::protobuf::host_protoc
19662007 PROPERTIES IMPORTED_LOCATION "${PROTOBUF_HOST_COMPILER} " )
19672008
1968- add_dependencies (arrow::protobuf::host_protoc protobuf_ep_host )
2009+ add_dependencies (arrow::protobuf::host_protoc protobuf_fc_host )
19692010 endif ()
1970- endmacro ()
2011+ list (POP_BACK CMAKE_MESSAGE_INDENT)
2012+ endfunction ()
19712013
19722014if (ARROW_WITH_PROTOBUF)
19732015 if (ARROW_FLIGHT_SQL)
@@ -2128,8 +2170,13 @@ macro(build_substrait)
21282170 SKIP_UNITY_BUILD_INCLUSION TRUE )
21292171 list (APPEND SUBSTRAIT_PROTO_GEN_ALL "${SUBSTRAIT_PROTO_GEN} .${EXT} " )
21302172 endforeach ()
2173+ # Add protobuf include directory for well-known types when using vendored protobuf
2174+ set (SUBSTRAIT_PROTOC_INCLUDES "-I${SUBSTRAIT_LOCAL_DIR} /proto" )
2175+ if (PROTOBUF_VENDORED AND Protobuf_INCLUDE_DIRS)
2176+ list (APPEND SUBSTRAIT_PROTOC_INCLUDES "-I${Protobuf_INCLUDE_DIRS} " )
2177+ endif ()
21312178 add_custom_command (OUTPUT "${SUBSTRAIT_PROTO_GEN} .cc" "${SUBSTRAIT_PROTO_GEN} .h"
2132- COMMAND ${ARROW_PROTOBUF_PROTOC} "-I ${SUBSTRAIT_LOCAL_DIR} /proto"
2179+ COMMAND ${ARROW_PROTOBUF_PROTOC} ${SUBSTRAIT_PROTOC_INCLUDES}
21332180 "--cpp_out=${SUBSTRAIT_CPP_DIR} "
21342181 "${SUBSTRAIT_LOCAL_DIR} /proto/substrait/${SUBSTRAIT_PROTO} .proto"
21352182 DEPENDS ${PROTO_DEPENDS} substrait_ep)
@@ -2147,10 +2194,15 @@ macro(build_substrait)
21472194 SKIP_UNITY_BUILD_INCLUSION TRUE )
21482195 list (APPEND SUBSTRAIT_PROTO_GEN_ALL "${ARROW_SUBSTRAIT_PROTO_GEN} .${EXT} " )
21492196 endforeach ()
2197+ # Add protobuf include directory for well-known types when using vendored protobuf
2198+ set (ARROW_SUBSTRAIT_PROTOC_INCLUDES "-I${SUBSTRAIT_LOCAL_DIR} /proto"
2199+ "-I${ARROW_SUBSTRAIT_PROTOS_DIR} " )
2200+ if (PROTOBUF_VENDORED AND Protobuf_INCLUDE_DIRS)
2201+ list (APPEND ARROW_SUBSTRAIT_PROTOC_INCLUDES "-I${Protobuf_INCLUDE_DIRS} " )
2202+ endif ()
21502203 add_custom_command (OUTPUT "${ARROW_SUBSTRAIT_PROTO_GEN} .cc"
21512204 "${ARROW_SUBSTRAIT_PROTO_GEN} .h"
2152- COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${SUBSTRAIT_LOCAL_DIR} /proto"
2153- "-I${ARROW_SUBSTRAIT_PROTOS_DIR} "
2205+ COMMAND ${ARROW_PROTOBUF_PROTOC} ${ARROW_SUBSTRAIT_PROTOC_INCLUDES}
21542206 "--cpp_out=${SUBSTRAIT_CPP_DIR} "
21552207 "${ARROW_SUBSTRAIT_PROTOS_DIR} /substrait/${ARROW_SUBSTRAIT_PROTO} .proto"
21562208 DEPENDS ${PROTO_DEPENDS} substrait_ep)
@@ -3228,6 +3280,9 @@ macro(build_grpc)
32283280 if (CARES_VENDORED)
32293281 add_dependencies (grpc_dependencies cares_fc)
32303282 endif ()
3283+ if (PROTOBUF_VENDORED)
3284+ add_dependencies (grpc_dependencies protobuf_fc)
3285+ endif ()
32313286
32323287 if (GFLAGS_VENDORED)
32333288 add_dependencies (grpc_dependencies gflags_ep)
@@ -3240,9 +3295,15 @@ macro(build_grpc)
32403295 add_dependencies (grpc_dependencies ${ARROW_PROTOBUF_LIBPROTOBUF} c-ares::cares
32413296 ZLIB::ZLIB)
32423297
3243- get_target_property (GRPC_PROTOBUF_INCLUDE_DIR ${ARROW_PROTOBUF_LIBPROTOBUF}
3244- INTERFACE_INCLUDE_DIRECTORIES )
3245- get_filename_component (GRPC_PB_ROOT "${GRPC_PROTOBUF_INCLUDE_DIR} " DIRECTORY )
3298+ # For FetchContent Protobuf, use the install prefix directly
3299+ if (PROTOBUF_VENDORED)
3300+ set (GRPC_PB_ROOT "${PROTOBUF_PREFIX} " )
3301+ else ()
3302+ get_target_property (GRPC_PROTOBUF_INCLUDE_DIR ${ARROW_PROTOBUF_LIBPROTOBUF}
3303+ INTERFACE_INCLUDE_DIRECTORIES )
3304+ get_filename_component (GRPC_PB_ROOT "${GRPC_PROTOBUF_INCLUDE_DIR} " DIRECTORY )
3305+ endif ()
3306+
32463307 get_target_property (GRPC_Protobuf_PROTOC_LIBRARY ${ARROW_PROTOBUF_LIBPROTOC}
32473308 IMPORTED_LOCATION )
32483309
@@ -3912,11 +3973,6 @@ function(build_orc)
39123973 INTERFACE_INCLUDE_DIRECTORIES )
39133974 get_filename_component (Protobuf_ROOT "${PROTOBUF_INCLUDE_DIR} " DIRECTORY )
39143975 set (PROTOBUF_HOME ${Protobuf_ROOT} )
3915- # ORC uses this.
3916- if (PROTOBUF_VENDORED)
3917- target_include_directories (${ARROW_PROTOBUF_LIBPROTOC}
3918- INTERFACE "${PROTOBUF_INCLUDE_DIR} " )
3919- endif ()
39203976 set (PROTOBUF_EXECUTABLE ${ARROW_PROTOBUF_PROTOC} )
39213977 set (PROTOBUF_LIBRARY ${ARROW_PROTOBUF_LIBPROTOBUF} )
39223978 set (PROTOC_LIBRARY ${ARROW_PROTOBUF_LIBPROTOC} )
0 commit comments