diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c92057f3777..bc1fb0327791 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -672,7 +672,11 @@ if(USE_IOS_RPC) add_subdirectory("apps/ios_rpc") endif() +set(TVM_CXX_STANDARD ${CMAKE_CXX_STANDARD}) +set(CMAKE_CXX_STANDARD 17) add_subdirectory(3rdparty/tvm-ffi) +set(CMAKE_CXX_STANDARD ${TVM_CXX_STANDARD}) +unset(TVM_CXX_STANDARD) if(TVM_DEBUG_WITH_ABI_CHANGE) message(STATUS "Building with debug code that may cause ABI changes...") diff --git a/tests/scripts/task_build.py b/tests/scripts/task_build.py index c6c30c9bbd98..e88fc2b38273 100755 --- a/tests/scripts/task_build.py +++ b/tests/scripts/task_build.py @@ -17,9 +17,11 @@ # under the License. # ruff: noqa: E402 import argparse +import json import logging import multiprocessing import os +import re import shutil import sys from pathlib import Path @@ -29,6 +31,68 @@ sys.path.append(str(REPO_ROOT / "ci" / "scripts" / "jenkins")) from cmd_utils import REPO_ROOT, Sh, init_log + +def _check_cxx_standard(build_dir): + compile_commands_path = REPO_ROOT / build_dir / "compile_commands.json" + with open(compile_commands_path, encoding="utf-8") as compile_commands_file: + compile_commands = json.load(compile_commands_file) + + standard_flag_pattern = re.compile(r"^(?:-std=(?:c|gnu)\+\+|/std:c\+\+)(.+)$", re.IGNORECASE) + tvm_ffi_commands = [] + tvm_commands = [] + + for compile_command in compile_commands: + source = Path(compile_command["file"]) + if not source.is_absolute(): + source = Path(compile_command["directory"]) / source + try: + source = source.resolve().relative_to(REPO_ROOT) + except ValueError: + continue + + if source.suffix.lower() not in {".cc", ".cpp", ".cxx"}: + continue + + arguments = compile_command.get("arguments") + if arguments is None: + arguments = compile_command["command"].split() + standard_flags = [] + for argument in arguments: + argument = argument.strip("\"'") + match = standard_flag_pattern.match(argument) + if match: + standard_flags.append((argument, match.group(1).lower())) + + if source.parts[:2] == ("3rdparty", "tvm-ffi"): + tvm_ffi_commands.append((source, standard_flags, compile_command)) + elif source.parts[0] == "src": + tvm_commands.append((source, standard_flags, compile_command)) + + if not tvm_ffi_commands: + raise RuntimeError("No C++ compile commands found for 3rdparty/tvm-ffi") + if not tvm_commands: + raise RuntimeError("No C++ compile commands found for TVM src/") + + for source, standard_flags, compile_command in tvm_ffi_commands: + if standard_flags and standard_flags[-1][1] not in {"17", "1z"}: + raise RuntimeError( + f"tvm-ffi source {source} must use C++17, but its compile command contains " + f"{', '.join(flag for flag, _ in standard_flags)}: {compile_command}" + ) + + for source, standard_flags, compile_command in tvm_commands: + if not standard_flags or standard_flags[-1][1] not in {"20", "2a"}: + raise RuntimeError( + f"TVM source {source} must use C++20, but its compile command is: {compile_command}" + ) + + logging.info( + "Verified C++ standards in %s tvm-ffi and %s TVM compile commands", + len(tvm_ffi_commands), + len(tvm_commands), + ) + + if __name__ == "__main__": init_log() @@ -90,6 +154,8 @@ else: sh.run("cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo ..", cwd=build_dir) + _check_cxx_standard(build_dir) + target = "" if args.cmake_target: target = args.cmake_target