From 7e9f3c8222b40d8d399221f5af8cff27b2428750 Mon Sep 17 00:00:00 2001 From: agent Date: Sun, 9 Aug 2026 11:43:52 -0700 Subject: [PATCH] fix(algo): gate icebug behind ICEBUG_ENABLED, fail soft on download error - Top-level CMakeLists adds option(ICEBUG_ENABLED ON) so icebug can be disabled explicitly (-DICEBUG_ENABLED=OFF) or as a fallback when the GitHub prebuilt download fails (offline CI, rate limit, etc.). - download_icebug.cmake early-returns on -DICEBUG_ENABLED=OFF and, on a failed file(DOWNLOAD), emits a WARNING, flips ICEBUG_ENABLED to OFF (FORCE'd so re-configures don't re-fail), and returns with empty ICEBUG_* vars instead of fatal-erroring configure. - Top-level CMakeLists gates find_package(Arrow), the icebug include dirs, lib linkage, and rpath behind ICEBUG_ENABLED. find_package(OpenMP) stays unconditional (other algos use ). - function/CMakeLists drops gds_page_rank.cpp + Arrow::arrow_shared when disabled; main/CMakeLists + algo_extension.cpp gate the GDS_PAGE_RANK registration and ARROW_DEFAULT_MEMORY_POOL setup behind #ifdef ICEBUG_ENABLED via target_compile_definitions. --- algo/CMakeLists.txt | 37 +++++++++++++++++++++----------- algo/cmake/download_icebug.cmake | 28 +++++++++++++++++++++++- algo/src/function/CMakeLists.txt | 25 +++++++++++++++------ algo/src/main/CMakeLists.txt | 6 ++++++ algo/src/main/algo_extension.cpp | 4 ++++ 5 files changed, 81 insertions(+), 19 deletions(-) diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index 79b321ba..19701beb 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -1,18 +1,29 @@ -# --- icebug (NetworKit fork) + Arrow, for the icebug-backed GDS_* algorithms --- +# --- ICEBUG_ENABLED knob + icebug (NetworKit fork) + Arrow, for the GDS_* algorithms --- # Pulls the prebuilt icebug release into vendor/; Arrow + OpenMP are system deps. +# If the prebuilt download fails (offline CI, GitHub rate limit, ...), download_icebug.cmake +# flips ICEBUG_ENABLED to OFF and emits a WARNING so configure still succeeds — the algo +# extension then builds without the GDS_* bridge (the hand-rolled algos still work, just no +# GDS_PAGE_RANK). Pass -DICEBUG_ENABLED=OFF to skip the network round-trip entirely. +option(ICEBUG_ENABLED "Enable icebug-backed GDS_* algorithms (requires outbound HTTPS to github.com)" ON) + include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/download_icebug.cmake) + # Help find_package locate Homebrew Arrow/OpenMP on macOS dev machines (no-op elsewhere). if (APPLE AND EXISTS "/opt/homebrew/opt/apache-arrow") list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew/opt/apache-arrow" "/opt/homebrew/opt/libomp") endif () -find_package(Arrow REQUIRED) +if (ICEBUG_ENABLED) + find_package(Arrow REQUIRED) +endif () find_package(OpenMP REQUIRED) include_directories( ${PROJECT_SOURCE_DIR}/src/include ${CMAKE_BINARY_DIR}/src/include - src/include - ${ICEBUG_INCLUDE_DIR}) + src/include) +if (ICEBUG_ENABLED) + include_directories(${ICEBUG_INCLUDE_DIR}) +endif () add_subdirectory(src/main) add_subdirectory(src/function) @@ -26,11 +37,13 @@ if (BUILD_STATIC_EXTENSION) else () set(_algo_target lbug_algo_extension) endif () -target_link_libraries(${_algo_target} PRIVATE - ${ICEBUG_LIB} - Arrow::arrow_shared - OpenMP::OpenMP_CXX) -# Let the loaded extension find a shared libnetworkit (prebuilt path); harmless for a static lib. -set_target_properties(${_algo_target} PROPERTIES - BUILD_RPATH "${ICEBUG_RPATH_DIR}" - INSTALL_RPATH "${ICEBUG_RPATH_DIR}") +if (ICEBUG_ENABLED) + target_link_libraries(${_algo_target} PRIVATE + ${ICEBUG_LIB} + Arrow::arrow_shared + OpenMP::OpenMP_CXX) + # Let the loaded extension find a shared libnetworkit (prebuilt path); harmless for a static lib. + set_target_properties(${_algo_target} PROPERTIES + BUILD_RPATH "${ICEBUG_RPATH_DIR}" + INSTALL_RPATH "${ICEBUG_RPATH_DIR}") +endif () diff --git a/algo/cmake/download_icebug.cmake b/algo/cmake/download_icebug.cmake index b5df0902..336a1c5b 100644 --- a/algo/cmake/download_icebug.cmake +++ b/algo/cmake/download_icebug.cmake @@ -4,6 +4,20 @@ # Default: download the prebuilt release for this platform into vendor/ (Arrow + OpenMP stay # system deps). Dev override: set -DICEBUG_SOURCE_DIR= to link a # local source build instead (e.g. when the prebuilt's pinned Arrow version differs from yours). +# +# Reads the ICEBUG_ENABLED cache option from the parent CMakeLists.txt. If it's OFF we leave +# ICEBUG_INCLUDE_DIR / ICEBUG_LIB / ICEBUG_RPATH_DIR empty and return immediately. If the +# prebuilt download fails (offline CI, GitHub rate limit, etc.) we flip ICEBUG_ENABLED to OFF +# (cached, so re-configures don't re-fail), emit a WARNING, and return — the algo extension +# then builds without the GDS_* bridge instead of aborting configure. + +if (NOT ICEBUG_ENABLED) + message(STATUS "icebug: disabled via -DICEBUG_ENABLED=OFF; skipping download + lib resolution") + set(ICEBUG_INCLUDE_DIR "") + set(ICEBUG_LIB "ICEBUG_LIB-NOTFOUND") + set(ICEBUG_RPATH_DIR "") + return() +endif () if (NOT DEFINED ICEBUG_SOURCE_DIR AND DEFINED ENV{ICEBUG_SOURCE_DIR}) set(ICEBUG_SOURCE_DIR "$ENV{ICEBUG_SOURCE_DIR}") @@ -51,7 +65,19 @@ if (NOT EXISTS "${ICEBUG_VENDOR_DIR}/lib") file(DOWNLOAD "${_ib_url}" "${ICEBUG_VENDOR_DIR}/${_ib_asset}" STATUS _ib_dl SHOW_PROGRESS) list(GET _ib_dl 0 _ib_dl_code) if (NOT _ib_dl_code EQUAL 0) - message(FATAL_ERROR "Failed to download icebug (${_ib_url}): ${_ib_dl}") + message(WARNING + "Failed to download icebug prebuilt (${_ib_url}): ${_ib_dl}\n" + " Disabling ICEBUG_ENABLED; the algo extension will still build with the " + "hand-rolled algos (PAGE_RANK, SCC, etc.) but GDS_* functions won't be available.\n" + " To re-enable, ensure outbound HTTPS to github.com works, pre-populate " + "extension/algo/vendor/ with the prebuilt, or pass " + "-DICEBUG_SOURCE_DIR=.") + set(ICEBUG_INCLUDE_DIR "") + set(ICEBUG_LIB "ICEBUG_LIB-NOTFOUND") + set(ICEBUG_RPATH_DIR "") + # Force so re-configures don't retry the failing download. + set(ICEBUG_ENABLED OFF CACHE BOOL "Enable icebug-backed GDS_* algorithms" FORCE) + return() endif () file(ARCHIVE_EXTRACT INPUT "${ICEBUG_VENDOR_DIR}/${_ib_asset}" DESTINATION "${ICEBUG_VENDOR_DIR}") endif () diff --git a/algo/src/function/CMakeLists.txt b/algo/src/function/CMakeLists.txt index 205e53fd..f70da82c 100644 --- a/algo/src/function/CMakeLists.txt +++ b/algo/src/function/CMakeLists.txt @@ -1,21 +1,34 @@ add_subdirectory(config) -add_library(lbug_algo_function - OBJECT +set(_algo_function_sources component_ids.cpp strongly_connected_components.cpp strongly_connected_components_kosaraju.cpp weakly_connected_components.cpp page_rank.cpp - gds_page_rank.cpp k_core_decomposition.cpp louvain.cpp spanning_forest.cpp ) +if (ICEBUG_ENABLED) + # gds_page_rank.cpp includes NetworKit + Arrow headers. Linking the imported targets to the + # object library propagates their compile flags + include dirs to it. + list(APPEND _algo_function_sources gds_page_rank.cpp) +endif () + +add_library(lbug_algo_function + OBJECT + ${_algo_function_sources}) -# gds_page_rank.cpp includes NetworKit + Arrow headers (Arrow pulls in ). Linking the -# imported targets to the object library propagates their compile flags + include dirs to it. -target_link_libraries(lbug_algo_function PRIVATE Arrow::arrow_shared OpenMP::OpenMP_CXX) +if (ICEBUG_ENABLED) + target_link_libraries(lbug_algo_function PRIVATE Arrow::arrow_shared OpenMP::OpenMP_CXX) + # ICEBUG_ENABLED is read by gds_page_rank.cpp via #ifdef to skip its body when icebug is off + # (defensive: source isn't compiled in that case, but matches the header-side guard). + target_compile_definitions(lbug_algo_function PRIVATE ICEBUG_ENABLED) +else () + # Other sources still use for parallel regions, so keep the OpenMP link — just drop Arrow. + target_link_libraries(lbug_algo_function PRIVATE OpenMP::OpenMP_CXX) +endif () set(ALGO_EXTENSION_OBJECT_FILES ${ALGO_EXTENSION_OBJECT_FILES} $ diff --git a/algo/src/main/CMakeLists.txt b/algo/src/main/CMakeLists.txt index 91d0ef1b..7d4d1f23 100644 --- a/algo/src/main/CMakeLists.txt +++ b/algo/src/main/CMakeLists.txt @@ -3,6 +3,12 @@ add_library(algo_extension_main algo_extension.cpp ) +if (ICEBUG_ENABLED) + # ICEBUG_ENABLED is read by algo_extension.cpp via #ifdef to gate the GDS_PAGE_RANK + # registration and the ARROW_DEFAULT_MEMORY_POOL setup. + target_compile_definitions(algo_extension_main PRIVATE ICEBUG_ENABLED) +endif () + set(ALGO_EXTENSION_OBJECT_FILES ${ALGO_EXTENSION_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/algo/src/main/algo_extension.cpp b/algo/src/main/algo_extension.cpp index ec7fe10b..4a5b3421 100644 --- a/algo/src/main/algo_extension.cpp +++ b/algo/src/main/algo_extension.cpp @@ -11,6 +11,7 @@ namespace algo_extension { using namespace extension; void AlgoExtension::load(main::ClientContext* context) { +#if defined(ICEBUG_ENABLED) // Arrow's default memory pool is mimalloc-backed, and mimalloc's per-thread init is not // safe on threads that predate libarrow's dlopen — GDS functions allocating Arrow buffers // from ladybug worker threads segfault in _mi_thread_init (non-deterministically; ~half of @@ -18,6 +19,7 @@ void AlgoExtension::load(main::ClientContext* context) { // first used; Arrow reads this env var lazily, and load() runs before any GDS allocation. // overwrite=0 respects a user-provided value. setenv("ARROW_DEFAULT_MEMORY_POOL", "system", 0); +#endif auto& db = *context->getDatabase(); ExtensionUtils::addTableFunc(db); ExtensionUtils::addTableFuncAlias(db); @@ -27,7 +29,9 @@ void AlgoExtension::load(main::ClientContext* context) { ExtensionUtils::addTableFuncAlias(db); ExtensionUtils::addTableFunc(db); ExtensionUtils::addTableFuncAlias(db); +#if defined(ICEBUG_ENABLED) ExtensionUtils::addTableFunc(db); +#endif ExtensionUtils::addTableFunc(db); ExtensionUtils::addTableFuncAlias(db); ExtensionUtils::addTableFunc(db);