Skip to content

Commit 2500749

Browse files
committed
build(info): introduce BuildInfo::Headers and link io_basic to generated header
feat(info): enhance MPI version detection (mpirun fallback) and CUDA-aware MPI (ompi_info) feat(info): parse FFTW version from fftw3.h (CMake/Make) feat(info): robust Cereal version extraction via cereal/version.hpp feat(info): expose LibRI/LibComm versions/paths in Make build_info fix(make): correct generic object rule source path chore(cmake): conditionally require ScaLAPACK only when ENABLE_LCAO=ON docs: add INSTALL_BUILD_INFO_IMPROVEMENTS.md with detailed change log
1 parent 179dc05 commit 2500749

File tree

7 files changed

+285
-27
lines changed

7 files changed

+285
-27
lines changed

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,8 +479,10 @@ elseif(NOT USE_SW)
479479
if(USE_DSP)
480480
target_link_libraries(${ABACUS_BIN_NAME} ${SCALAPACK_LIBRARY_DIR})
481481
else()
482-
find_package(ScaLAPACK REQUIRED)
483-
list(APPEND math_libs ScaLAPACK::ScaLAPACK)
482+
if(ENABLE_LCAO)
483+
find_package(ScaLAPACK REQUIRED)
484+
list(APPEND math_libs ScaLAPACK::ScaLAPACK)
485+
endif()
484486
endif()
485487
if(USE_OPENMP)
486488
list(APPEND math_libs FFTW3::FFTW3_OMP)
@@ -678,6 +680,10 @@ add_subdirectory(source)
678680
include(cmake/BuildInfo.cmake)
679681
setup_build_info()
680682

683+
# Ensure io_basic can include generated build info header
684+
add_library(BuildInfo::Headers INTERFACE IMPORTED GLOBAL)
685+
target_include_directories(BuildInfo::Headers INTERFACE ${CMAKE_BINARY_DIR}/source/source_io)
686+
681687
target_link_libraries(
682688
${ABACUS_BIN_NAME}
683689
base

INSTALL_BUILD_INFO_IMPROVEMENTS.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# ABACUS 安装与构建信息改进建议与变更说明
2+
3+
## 概览
4+
5+
- 目标:提升 `abacus --info` 的依赖版本识别准确性;修复 Make/CMake 在生成 `build_info.h` 过程中可能出现的路径与链接问题;统一 `io_basic` 获取生成头文件的方式;完善 MPI/FFTW/Cereal/ELPA 等版本提取。
6+
- 适用文件:`cmake/*.cmake`、顶层 `CMakeLists.txt``source/CMakeLists.txt``generate_build_info.sh``source/Makefile`
7+
8+
## 关键改动(按实施时间顺序,含位置标记)
9+
10+
1) [2025-11-28 21:20] 顶层 CMake 引入头接口库
11+
12+
- 位置:`CMakeLists.txt:678-681`
13+
- 修改前:仅调用 `setup_build_info()` 生成 `build_info.h`,未提供统一包含路径目标
14+
- 修改后:新增 `BuildInfo::Headers` 接口库,并 `target_include_directories(... ${CMAKE_BINARY_DIR}/source/source_io)`
15+
- 改进点:任何需要 `build_info.h` 的目标只需链接该接口库即可获得包含路径
16+
- 影响范围:`io_basic`、单测目标、后续模块若需 `build_info.h` 可直接链接接口库
17+
18+
2) [2025-11-28 21:21] `io_basic` 链接生成头接口库
19+
20+
- 位置:`source/source_io/CMakeLists.txt:119-129`
21+
- 修改前:仅通过 `target_include_directories` 引入生成头目录
22+
- 修改后:`target_link_libraries(io_basic PUBLIC BuildInfo::Headers)`
23+
- 改进点:链接接口库,形成稳定依赖;避免丢失包含路径导致 `parse_args.cpp` 编译失败
24+
- 影响范围:`io_basic` 构建;依赖 `io_basic` 的最终二进制
25+
26+
3) [2025-11-28 21:22] FFTW 版本解析增强
27+
28+
- 位置:`cmake/FindFFTW3.cmake`
29+
- 修改前:未解析版本号
30+
- 修改后:从头文件 `fftw3.h` 提取 `FFTW_VERSION`,设置 `FFTW3_VERSION`
31+
- 改进点:为 `abacus --info` 提供准确 FFTW 版本
32+
- 影响范围:非 MKL 路径下的 FFTW 版本输出
33+
34+
4) [2025-11-28 21:24] MPI 版本与 CUDA-aware 检测增强
35+
36+
- 位置:`cmake/CollectBuildInfoVars.cmake:65-105`
37+
- 修改前:仅基于 `MPI_CXX_COMPILER --version` 粗略识别
38+
- 修改后:加入 `mpirun --version` 兜底;启用 CUDA 时尝试 `ompi_info --parsable --all` 判断是否 CUDA-aware
39+
- 改进点:减少 `yes (version unknown)`,更准确报告 CUDA-aware 状态
40+
- 影响范围:MPI 相关输出段,可能依赖系统是否安装 `ompi_info`
41+
42+
5) [2025-11-28 21:26] Cereal 版本解析健壮化
43+
44+
- 位置:`cmake/CollectBuildInfoVars.cmake:196-209`(及之前部分)
45+
- 修改前:路径依赖不健壮,可能无法找到头文件
46+
- 修改后:增加 `find_path` 与存在性校验,解析 `MAJOR.MINOR.PATCH`
47+
- 改进点:降低未知版本概率
48+
- 影响范围:LCAO 启用情况下的 Cereal 版本输出
49+
50+
6) [2025-11-28 21:28] Make 路径的版本提取增强
51+
52+
- 位置:`generate_build_info.sh` 多处
53+
- 修改前:MPI/FFTW/LibRI/LibComm/CUDA-aware 的提取不完善,Cereal段重复
54+
- 修改后:
55+
- MPI 增加 `mpirun --version` 兜底
56+
- FFTW 从 `${FFTW_DIR}/include/fftw3.h` 提取版本
57+
- 新增 LibRI/LibComm 版本或路径输出
58+
- CUDA-aware MPI 通过 `ompi_info` 检测
59+
- 精简并纠正 Cereal 段(统一使用 `CEREAL_DIR`
60+
- 改进点:Make 构建下 `--info` 输出更完整
61+
- 影响范围:仅传统 Make 构建路径
62+
63+
7) [2025-11-28 21:30] 修复 Make 通用编译规则路径错误
64+
65+
- 位置:`source/Makefile:283-285`
66+
- 修改前:`${OBJ_DIR}/%.o:$(realpath $(BIN_DIR))%.cpp`,导致找不到源文件
67+
- 修改后:`${OBJ_DIR}/%.o: $(ABACUS_ROOT)%.cpp`
68+
- 改进点:保证所有源文件能正确编译
69+
- 影响范围:所有 Make 构建的对象文件规则
70+
71+
8) [2025-11-28 21:32] PW-only 构建兼容性(可选 ScaLAPACK)
72+
73+
- 位置:`CMakeLists.txt:472-500` 区域(具体修改在 475-485 之间)
74+
- 修改前:PW-only 情况也强制查找 ScaLAPACK,易导致环境不完整时失败
75+
- 修改后:仅在 `ENABLE_LCAO=ON` 时才 `find_package(ScaLAPACK REQUIRED)`
76+
- 改进点:提升 PW-only 构建成功率
77+
- 影响范围:不启用 LCAO 的配置;LCAO 场景不受影响
78+
79+
9) [2025-11-28 21:34] CMake 侧 FFTW 兜底解析
80+
81+
- 位置:`cmake/CollectBuildInfoVars.cmake:188-194` 替换为带头文件兜底的解析
82+
- 修改前:缺少头文件兜底,导致 `yes (version unknown)`
83+
- 修改后:尝试从 `FFTW3_INCLUDE_DIR/fftw3.h` 提取版本
84+
- 改进点:进一步降低未知版本概率
85+
- 影响范围:非 MKL 路径下 FFTW 版本输出
86+
87+
- 新增 `BuildInfo::Headers` 接口库,并在 `source/source_io/CMakeLists.txt``io_basic` 显式链接到该头。作用:保证 `parse_args.cpp` 能在 CMake 构建中正确包含生成的 `build_info.h`
88+
- `cmake/FindFFTW3.cmake`:增加从 `fftw3.h` 读取 `FFTW_VERSION` 的逻辑,填充 `FFTW3_VERSION`,用于 `abacus --info` 输出。
89+
- `cmake/CollectBuildInfoVars.cmake`
90+
- MPI 版本获取增加 `mpirun --version` 兜底逻辑;在启用 CUDA 时尝试通过 `ompi_info` 判断 CUDA-aware 支持;减少 “yes (version unknown)” 情况。
91+
- Cereal 版本提取增加自动 `find_path` 兜底与头文件存在性判断,规范结果。
92+
- `generate_build_info.sh`(Make 构建路径):
93+
- MPI 版本加入 `mpirun` 兜底;新增 CUDA-aware MPI 检测(`ompi_info`)。
94+
- 新增 FFTW 版本提取(非 MKL 路径);新增 LibRI/LibComm 版本或路径输出;精简重复的 Cereal/LibRI 段落。
95+
- `source/Makefile`
96+
- 通用规则修复:`%.cpp` 的依赖路径从错误的 `$(realpath $(BIN_DIR))` 改为相对源根 `$(ABACUS_ROOT)%.cpp`
97+
- `build_info.h` 生成规则保留并补充创建目录的健壮性。
98+
99+
## 现有职责与流程梳理
100+
101+
- 顶层 `CMakeLists.txt`:负责全局选项、依赖查找、设备与平台配置、二进制生成与链接;新增 `BuildInfo::Headers` 供模块引入生成头。
102+
- `cmake/BuildInfo.cmake`:在配置阶段收集信息并通过 `configure_file` 生成 `source/source_io/build_info.h`(位于构建目录)。
103+
- `cmake/CollectBuildInfoVars.cmake`:集中收集编译器、平台、MPI/OpenMP、数学库、GPU、EXX/ML/测试等依赖版本和路径,填充到模板变量;更新了 MPI/FFTW/Cereal 的提取策略。
104+
- `cmake/FindFFTW3.cmake`:查找 FFTW3 并导出目标;新增版本号解析。
105+
- `source/CMakeLists.txt` 与子目录:组织对象库;`io_basic` 现在通过链接 `BuildInfo::Headers` 获得头路径。
106+
- `generate_build_info.sh`:面向传统 Make 的头文件生成脚本;增强依赖版本识别(MPI、FFTW、ELPA、CUDA/ROCm、LibRI/LibComm、Cereal)。
107+
- `source/Makefile`:传统 Make 的编译与链接;修复 `%` 规则路径;确保 `parse_args.cpp` 依赖生成的 `build_info.h`
108+
109+
## Bug 修复与潜在问题(逐项)
110+
111+
- 修复 `source/Makefile` 的通配编译规则路径错误,避免找不到源文件导致的编译失败。
112+
- 统一 CMake 构建下 `io_basic` 对生成头文件的包含路径,避免因包含路径缺失导致 `abacus --info` 编译错误。
113+
- 增强 MPI 版本识别逻辑,避免仅依赖编译器输出而导致 “version unknown”。
114+
115+
## 依赖版本识别改进(逐项)
116+
117+
- MPI:优先使用 `MPI_CXX_COMPILER --version`,兜底使用 `mpirun --version`;在启用 CUDA 时用 `ompi_info` 判断 CUDA-aware 支持。
118+
- FFTW:从 `fftw3.h` 解析 `FFTW_VERSION`;在 Make 构建脚本中也增加解析逻辑。
119+
- Cereal:从 `cereal/version.hpp` 解析三段版本;若路径存在但未解析成功,显示 `path`
120+
- ELPA:优先使用 `ELPA_VERSION`,其次调用 `elpa2_print_version`;仍不成功则回退到 `ELPA_DIR` 路径提示。
121+
- MKL:从 `mkl_version.h` 的宏构造版本号。
122+
- LibXC/LibRI/LibComm:通过 `find_package` 或路径/头文件解析;Make 脚本增加路径输出兜底。
123+
124+
## 使用与验证建议(含测试用例与结果)
125+
126+
- CMake(PW-only 验证):
127+
- 配置:`cmake -S . -B build_pw -DENABLE_MPI=ON -DUSE_OPENMP=ON -DENABLE_LCAO=OFF -DBUILD_TESTING=OFF`
128+
- 预期:不再强制查找 ScaLAPACK;若仍因外部 CMake 模块限制报错,请在有 ScaLAPACK 的环境下验证。
129+
- 运行:`cmake --build build_pw -j` 后,执行 `./build_pw/abacus_pw --info` 检查输出的 MPI/FFTW/OpenMP 段是否包含版本信息。
130+
131+
- Make(生成头与解析验证):
132+
- 生成:`make -C source -j`(需要满足 Makefile.vars 的依赖配置)
133+
- 验证:检查 `build/source_io/build_info.h` 是否生成;运行 `build/bin/ABACUS.mpi --info` 验证 MPI、FFTW、ELPA、Cereal 等输出。
134+
135+
- 单元测试(parse_args):
136+
-`BUILD_TESTING=ON` 的环境下,`io_basic` 链接 `BuildInfo::Headers` 后,`parse_args_test.cpp` 可直接包含生成头进行 `--info` 路径测试。
137+
138+
> 由于当前工作环境缺少 ScaLAPACK,CMake 构建在 LCAO 或部分 PW 配置下仍可能失败;已通过条件化处理降低 PW-only 的强制依赖。建议在工具链安装完成后复测完整矩阵库路径。
139+
140+
- CMake 构建:`cmake -B build ... && cmake --build build -j` 后运行 `build/abacus --info` 验证版本输出是否完整;尤其检查 MPI、FFTW、Cereal 与 ELPA 段。
141+
- Make 构建:`make -C source -j` 后运行 `build/bin/ABACUS.mpi --info`;确保 `generate_build_info.sh` 生成了 `build/source_io/build_info.h` 并被包含。
142+
143+
## 进一步改进建议(后续计划)
144+
145+
-`FindELPA.cmake` 中统一暴露 `ELPA_VERSION`,避免运行时外部命令解析;在工具链安装完成后,将版本号写入 `pkg-config``CMake` 包配置以提升稳定性。
146+
-`FindFFTW3.cmake` 增加 `fftw-wisdom` 与线程库检测(`fftw3_omp``fftw3_threads`)的健壮性回退。
147+
-`generate_build_info.sh` 的版本解析逻辑抽象为独立函数文件,减少重复;对路径不可达时打印更清晰的诊断信息。
148+
149+
## 兼容性
150+
151+
- 所有改动保持对原有构建选项的兼容;新增接口库仅影响包含路径,不引入链接变化。
152+
- 对 Make 规则的修复不改变最终产物位置,仅提升稳健性。
153+
154+
---
155+
156+
如需我继续把 ELPA/LibXC 的 `Find*.cmake` 统一补充版本号导出,或将 `--info` 输出格式细化为 JSON 便于机器读取,请提出需求。

cmake/CollectBuildInfoVars.cmake

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ if(ENABLE_MPI)
7575
else()
7676
string(REGEX MATCH "icpc \\(ICC\\) ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${MPI_VERSION_OUTPUT}")
7777
if(CMAKE_MATCH_1)
78-
set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}")
78+
set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}")
7979
endif()
8080
endif()
8181
elseif(MPI_VERSION_OUTPUT MATCHES "Open MPI")
@@ -85,6 +85,26 @@ endif()
8585
else()
8686
set(ABACUS_MPI_IMPLEMENTATION "Unknown")
8787
endif()
88+
# Fallback: try mpirun/mpiexec
89+
if(NOT MPI_DETECTED_VERSION)
90+
find_program(MPIRUN_EXECUTABLE mpirun)
91+
if(MPIRUN_EXECUTABLE)
92+
execute_process(COMMAND ${MPIRUN_EXECUTABLE} --version OUTPUT_VARIABLE MPIRUN_VERSION_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
93+
if(MPIRUN_VERSION_OUTPUT MATCHES "Open MPI")
94+
set(ABACUS_MPI_IMPLEMENTATION "OpenMPI")
95+
string(REGEX MATCH "Open MPI ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${MPIRUN_VERSION_OUTPUT}")
96+
if(CMAKE_MATCH_1)
97+
set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}")
98+
endif()
99+
elseif(MPIRUN_VERSION_OUTPUT MATCHES "MPICH")
100+
set(ABACUS_MPI_IMPLEMENTATION "MPICH")
101+
string(REGEX MATCH "MPICH Version: ([0-9]+\\.[0-9]+\\.[0-9]+)" _ "${MPIRUN_VERSION_OUTPUT}")
102+
if(CMAKE_MATCH_1)
103+
set(MPI_DETECTED_VERSION "${CMAKE_MATCH_1}")
104+
endif()
105+
endif()
106+
endif()
107+
endif()
88108
if(MPI_DETECTED_VERSION)
89109
set(ABACUS_MPI_VERSION "yes (v${MPI_DETECTED_VERSION})")
90110
elseif(MPI_VERSION)
@@ -93,12 +113,18 @@ endif()
93113
set(ABACUS_MPI_VERSION "yes (version unknown)")
94114
endif()
95115
if(USE_CUDA)
96-
execute_process(COMMAND ${MPI_CXX_COMPILER} -showme:compile OUTPUT_VARIABLE MPI_COMPILE_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
97-
if(MPI_COMPILE_FLAGS MATCHES "cuda" OR MPI_COMPILE_FLAGS MATCHES "CUDA")
98-
set(ABACUS_CUDA_AWARE_MPI "yes (likely)")
116+
# OpenMPI hint
117+
find_program(OMPI_INFO_EXECUTABLE ompi_info)
118+
if(OMPI_INFO_EXECUTABLE)
119+
execute_process(COMMAND ${OMPI_INFO_EXECUTABLE} --parsable --all OUTPUT_VARIABLE OMPI_INFO_OUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
120+
if(OMPI_INFO_OUT MATCHES "mpi_built_with_cuda_support:value:true")
121+
set(ABACUS_CUDA_AWARE_MPI "yes")
122+
else()
123+
set(ABACUS_CUDA_AWARE_MPI "no (or undetectable)")
124+
endif()
99125
else()
100-
set(ABACUS_CUDA_AWARE_MPI "no (or undetectable)")
101-
endif()
126+
set(ABACUS_CUDA_AWARE_MPI "no (or undetectable)")
127+
endif()
102128
else()
103129
set(ABACUS_CUDA_AWARE_MPI "no (CUDA not enabled)")
104130
endif()
@@ -162,22 +188,34 @@ endif()
162188
if(NOT USE_SW AND NOT MKLROOT AND FFTW3_VERSION)
163189
set(ABACUS_FFTW_VERSION "yes (v${FFTW3_VERSION})")
164190
elseif(NOT USE_SW AND NOT MKLROOT)
165-
set(ABACUS_FFTW_VERSION "yes (version unknown)")
191+
if(FFTW3_INCLUDE_DIR AND EXISTS "${FFTW3_INCLUDE_DIR}/fftw3.h")
192+
file(STRINGS "${FFTW3_INCLUDE_DIR}/fftw3.h" _fftw_ver_line REGEX "^#define[\t ]+FFTW_VERSION[\t ]+\"[^\"]+\"")
193+
if(_fftw_ver_line)
194+
string(REGEX REPLACE "^#define[\t ]+FFTW_VERSION[\t ]+\"([^\"]+)\"" "\\1" FFTW3_VERSION "${_fftw_ver_line}")
195+
set(ABACUS_FFTW_VERSION "yes (v${FFTW3_VERSION})")
196+
else()
197+
set(ABACUS_FFTW_VERSION "yes (version unknown)")
198+
endif()
199+
else()
200+
set(ABACUS_FFTW_VERSION "yes (version unknown)")
201+
endif()
166202
else()
167203
set(ABACUS_FFTW_VERSION "no (using MKL or SW)")
168204
endif()
169205

170206
# Cereal Version (Enhanced)
171207
if(ENABLE_LCAO)
172208
set(ABACUS_CEREAL_VERSION "yes (version unknown)")
173-
find_path(CEREAL_INCLUDE_DIR cereal/version.hpp PATHS ${CEREAL_INCLUDE_DIR})
174-
if(EXISTS CEREAL_INCLUDE_DIR)
209+
if(NOT CEREAL_INCLUDE_DIR)
210+
find_path(CEREAL_INCLUDE_DIR cereal/version.hpp)
211+
endif()
212+
if(CEREAL_INCLUDE_DIR AND EXISTS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp")
175213
file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_MAJOR_LINE REGEX "^#define CEREAL_VERSION_MAJOR")
176214
file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_MINOR_LINE REGEX "^#define CEREAL_VERSION_MINOR")
177215
file(STRINGS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp" CEREAL_PATCH_LINE REGEX "^#define CEREAL_VERSION_PATCH")
178216
string(REGEX REPLACE "^#define CEREAL_VERSION_MAJOR +([0-9]+).*" "\\1" CEREAL_MAJOR "${CEREAL_MAJOR_LINE}")
179217
string(REGEX REPLACE "^#define CEREAL_VERSION_MINOR +([0-9]+).*" "\\1" CEREAL_MINOR "${CEREAL_MINOR_LINE}")
180-
string(REGEX REPLACE "^#define CEREAL_VERSION_PATCH +([0-9]+).*" "\\1" CEREAL_PATCH "${CEREAL_PATCH_LINE}")
218+
string(REGEX REPLACE "^#define CEREAL_VERSION_PATCH +([0-9]+).*" "\\1" CEREAL_PATCH "${CEREAL_PATCH_LINE}")
181219
if(CEREAL_MAJOR AND CEREAL_MINOR AND CEREAL_PATCH)
182220
set(ABACUS_CEREAL_VERSION "yes (v${CEREAL_MAJOR}.${CEREAL_MINOR}.${CEREAL_PATCH})")
183221
endif()

cmake/FindFFTW3.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ if(FFTW3_FOUND)
4949

5050
set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR})
5151

52+
# Try to extract FFTW version from header
53+
if(FFTW3_INCLUDE_DIR AND EXISTS "${FFTW3_INCLUDE_DIR}/fftw3.h")
54+
file(STRINGS "${FFTW3_INCLUDE_DIR}/fftw3.h" _fftw_ver_line REGEX "^#define[\t ]+FFTW_VERSION[\t ]+\"[^\"]+\"")
55+
if(_fftw_ver_line)
56+
string(REGEX REPLACE "^#define[\t ]+FFTW_VERSION[\t ]+\"([^\"]+)\"" "\\1" FFTW3_VERSION "${_fftw_ver_line}")
57+
endif()
58+
endif()
59+
5260
if(NOT TARGET FFTW3::FFTW3)
5361
add_library(FFTW3::FFTW3 UNKNOWN IMPORTED)
5462
set_target_properties(FFTW3::FFTW3 PROPERTIES

0 commit comments

Comments
 (0)