Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions FairSoftConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install" CACHE PATH "Install prefi
# set(GEANT4MT OFF CACHE BOOL "Build Geant4 in multi-threading mode" FORCE)
# set(GEANT4MT ON CACHE BOOL "Build Geant4 in multi-threading mode" FORCE)

#
# CI Build Mode (default OFF)
#
# Enable this to reduce peak disk usage during builds. When enabled:
# - Packages are built sequentially (one at a time) instead of in parallel
# - Each package's build and source directories are removed after installation
# - Disk usage is logged (space reclaimed + total build tree size)
#
# The -j<ncpus> argument still parallelizes compilation within each package build.
# Trade-offs:
# - Builds take longer due to package serialization
# - Incremental rebuilds after failure are longer (removed packages must fully rebuild)
# Recommended for CI environments or systems with limited storage.
#
# set(CI_BUILD_MODE OFF CACHE BOOL "Serialize builds and remove package dirs after install" FORCE)
# set(CI_BUILD_MODE ON CACHE BOOL "Serialize builds and remove package dirs after install" FORCE)

Comment on lines +40 to +56
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fuhlig1 also documented here

#
# Python
#
Expand Down
44 changes: 44 additions & 0 deletions cmake/legacy.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,44 @@ add_custom_target(source-cache
COMMENT "Creating source cache at ${tarfile}"
)

# CI_BUILD_MODE: Serialize builds and remove package directories after install
if(NOT DEFINED CI_BUILD_MODE)
set(CI_BUILD_MODE OFF)
endif()

if(CI_BUILD_MODE)
foreach(pkg IN LISTS packages)
ExternalProject_Add_Step(${pkg} reclaim_diskspace
COMMAND ${CMAKE_COMMAND}
-DPACKAGE_NAME=${pkg}
-DPKG_BUILD_DIR=${CMAKE_BINARY_DIR}/Build/${pkg}
-DPKG_SOURCE_DIR=${CMAKE_BINARY_DIR}/Source/${pkg}
-DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}
-P ${CMAKE_SOURCE_DIR}/cmake/reclaim-diskspace.cmake
COMMENT "Removing ${pkg} package directories to reclaim disk space"
DEPENDEES install
ALWAYS OFF
)
endforeach()

# Serialize package builds to reduce peak disk usage in CI environments.
# This ensures only one package builds at a time, preventing multiple large
# package directories from existing simultaneously.
# Exclude optional packages (EXCLUDE_FROM_ALL) from the serial chain.
set(prev_pkg "")
foreach(pkg IN LISTS packages)
get_target_property(is_excluded ${pkg} EXCLUDE_FROM_ALL)
if(is_excluded)
continue()
endif()
if(prev_pkg)
ExternalProject_Add_StepDependencies(${pkg} configure ${prev_pkg})
endif()
set(prev_pkg ${pkg})
endforeach()
unset(prev_pkg)
endif()

include(CTest)

foreach(ver IN ITEMS 18.6 18.8 19.0)
Expand Down Expand Up @@ -604,6 +642,12 @@ if(SOURCE_CACHE)
else()
message(STATUS " ${Cyan}SOURCE CACHE${CR} using upstream URLs (generate cache by building target 'source-cache' and pass via ${BMagenta}-DSOURCE_CACHE=...${CR})")
endif()
message(STATUS " ")
if(CI_BUILD_MODE)
message(STATUS " ${Cyan}CI_BUILD_MODE${CR} ${BGreen}ON${CR} (serialized builds, package directories removed after install)")
else()
message(STATUS " ${Cyan}CI_BUILD_MODE${CR} ${BGreen}OFF${CR} (enable with ${BMagenta}-DCI_BUILD_MODE=ON${CR} to reduce disk usage)")
endif()
if(CMAKE_OSX_SYSROOT)
message(STATUS " ")
message(STATUS " ${Cyan}OSX_SYSROOT${CR} ${BGreen}${CMAKE_OSX_SYSROOT}${CR} (change with ${BMagenta}-DCMAKE_OSX_SYSROOT=...${CR})")
Expand Down
64 changes: 64 additions & 0 deletions cmake/reclaim-diskspace.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# reclaim-diskspace.cmake
# Remove package build/source directories after install to reclaim disk space
# Expected variables: PACKAGE_NAME, PKG_BUILD_DIR, PKG_SOURCE_DIR, CMAKE_BINARY_DIR

if(NOT DEFINED PACKAGE_NAME OR NOT DEFINED PKG_BUILD_DIR OR NOT DEFINED PKG_SOURCE_DIR)
message(FATAL_ERROR "PACKAGE_NAME, PKG_BUILD_DIR, and PKG_SOURCE_DIR must be defined")
endif()

# Helper function to measure directory size in MB
function(measure_dir_size_mb dir out_var out_success)
set(${out_success} FALSE PARENT_SCOPE)
set(${out_var} 0 PARENT_SCOPE)
if(UNIX)
find_program(DU_EXECUTABLE du)
if(DU_EXECUTABLE)
execute_process(
COMMAND ${DU_EXECUTABLE} -sk "${dir}"
OUTPUT_VARIABLE du_output
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(du_output)
string(REGEX REPLACE "^([0-9]+).*" "\\1" size_kb "${du_output}")
math(EXPR size_mb "${size_kb} / 1024")
set(${out_var} ${size_mb} PARENT_SCOPE)
set(${out_success} TRUE PARENT_SCOPE)
endif()
endif()
endif()
endfunction()

# Measure sizes before removal
measure_dir_size_mb("${PKG_BUILD_DIR}" build_mb build_ok)
measure_dir_size_mb("${PKG_SOURCE_DIR}" source_mb source_ok)

if(build_ok AND source_ok)
math(EXPR total_mb "${build_mb} + ${source_mb}")
message(STATUS "[${PACKAGE_NAME}] Reclaiming ~${total_mb} MB (build: ${build_mb}, source: ${source_mb})")
elseif(build_ok)
message(STATUS "[${PACKAGE_NAME}] Reclaiming ~${build_mb} MB")
elseif(source_ok)
message(STATUS "[${PACKAGE_NAME}] Reclaiming ~${source_mb} MB")
else()
message(STATUS "[${PACKAGE_NAME}] Removing package directories...")
endif()

# Remove package directories
execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf "${PKG_BUILD_DIR}" RESULT_VARIABLE build_rm)
execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf "${PKG_SOURCE_DIR}" RESULT_VARIABLE source_rm)

if(NOT build_rm EQUAL 0)
message(WARNING "[${PACKAGE_NAME}] Failed to remove package build directory")
endif()
if(NOT source_rm EQUAL 0)
message(WARNING "[${PACKAGE_NAME}] Failed to remove package source directory")
endif()

# Report total build tree size
if(DEFINED CMAKE_BINARY_DIR)
measure_dir_size_mb("${CMAKE_BINARY_DIR}" tree_mb tree_ok)
if(tree_ok)
message(STATUS "[${PACKAGE_NAME}] Build tree size: ${tree_mb} MB")
endif()
endif()