From 65b597b245b5238d0e04d87b94ada1aefdb2d67e Mon Sep 17 00:00:00 2001 From: Jiacheng Huang Date: Wed, 12 Aug 2026 04:12:36 +0800 Subject: [PATCH] fix(build): regenerate communication bridge for header changes --- CMakeLists.txt | 5 ++++ src/CMakeLists.txt | 17 +++++++++++ tests/CMakeLists.txt | 6 ++++ tests/bridge_dependency_contract.py | 44 +++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/bridge_dependency_contract.py diff --git a/CMakeLists.txt b/CMakeLists.txt index ebaca2c..565f79a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.18) project(InfiniCCL VERSION 0.1.0 LANGUAGES C CXX) +include(CTest) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -507,6 +509,9 @@ add_subdirectory(src) if(BUILD_EXAMPLES) add_subdirectory(examples) endif() +if(BUILD_TESTING) + add_subdirectory(tests) +endif() # ========================================================= # --- Installation --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e1e726..319a546 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,21 @@ set(AUTOGEN_WARNING [[/* file(GLOB CORE_SRCS "*.cc") file(GLOB_RECURSE BASE_IMPL_SRCS "base/*.cc") +file(GLOB_RECURSE BRIDGE_DEP_HEADERS CONFIGURE_DEPENDS + "base/*.h" + "backends/*.h" + "devices/*.h" + "devices/*.cuh" +) + +string(REPLACE ";" "\n" BRIDGE_DEPENDENCY_CONTENT "${BRIDGE_DEP_HEADERS}") +set(BRIDGE_DEPENDENCY_MANIFEST + "${CMAKE_CURRENT_BINARY_DIR}/bridge_dependencies.txt" +) +file(GENERATE + OUTPUT "${BRIDGE_DEPENDENCY_MANIFEST}" + CONTENT "${BRIDGE_DEPENDENCY_CONTENT}\n" +) target_sources(infiniccl PRIVATE ${CORE_SRCS} @@ -298,7 +313,9 @@ add_custom_command( "${BACK_STR}" DEPENDS "${PROJECT_SOURCE_DIR}/scripts/gen_bridge.py" "${PROJECT_SOURCE_DIR}/include/comm.h" + "${BRIDGE_DEPENDENCY_MANIFEST}" ${BASE_IMPL_SRCS} + ${BRIDGE_DEP_HEADERS} VERBATIM COMMENT "Generating InfiniCCL bridge and manifest files for Devices: [${DEV_STR}] Backends: [${BACK_STR}]..." ) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..4bbc216 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +add_test( + NAME bridge_dependency_contract + COMMAND ${Python3_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}/bridge_dependency_contract.py" + "${PROJECT_SOURCE_DIR}/src/CMakeLists.txt" +) diff --git a/tests/bridge_dependency_contract.py b/tests/bridge_dependency_contract.py new file mode 100644 index 0000000..8fdb553 --- /dev/null +++ b/tests/bridge_dependency_contract.py @@ -0,0 +1,44 @@ +import pathlib +import re +import sys + + +def main(): + source = pathlib.Path(sys.argv[1]).read_text(encoding="utf-8") + + header_glob = re.search( + r"file\(GLOB_RECURSE BRIDGE_DEP_HEADERS CONFIGURE_DEPENDS(.*?)\n\)", + source, + re.DOTALL, + ) + assert header_glob is not None + assert set(re.findall(r'"([^"]+)"', header_glob.group(1))) == { + "base/*.h", + "backends/*.h", + "devices/*.h", + "devices/*.cuh", + } + + assert re.search( + r"file\(GENERATE\s+" + r'OUTPUT "\$\{BRIDGE_DEPENDENCY_MANIFEST\}"\s+' + r'CONTENT "\$\{BRIDGE_DEPENDENCY_CONTENT\}\\n"\s*' + r"\)", + source, + ) + + bridge_command = re.search( + r"add_custom_command\(\s+" + r'OUTPUT "\$\{GENERATED_BRIDGE\}" "\$\{GENERATED_MANIFEST\}"' + r"(.*?)\n\)", + source, + re.DOTALL, + ) + assert bridge_command is not None + dependencies = bridge_command.group(1) + assert '"${BRIDGE_DEPENDENCY_MANIFEST}"' in dependencies + assert "${BRIDGE_DEP_HEADERS}" in dependencies + + +if __name__ == "__main__": + main()