Files
mlc-ai--mlc-llm/CMakeLists.txt
T
wehub-resource-sync 770d92cb1f
Lint / lint (push) Waiting to run
Windows CI / Windows (push) Waiting to run
Build Docs / Deploy Docs (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:23:58 +08:00

219 lines
7.7 KiB
CMake

cmake_minimum_required(VERSION 3.18)
project(mlc_llm C CXX)
include(CheckCXXCompilerFlag)
if(MSVC)
set(CMAKE_CXX_FLAGS "/fp:fast ${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "-ffast-math ${CMAKE_CXX_FLAGS}")
endif()
if(EXISTS ${CMAKE_BINARY_DIR}/config.cmake)
include(${CMAKE_BINARY_DIR}/config.cmake)
else()
if(EXISTS ${CMAKE_SOURCE_DIR}/config.cmake)
include(${CMAKE_SOURCE_DIR}/config.cmake)
endif()
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE
RelWithDebInfo
CACHE STRING "Build type" FORCE)
message(STATUS "Setting default build type to " ${CMAKE_BUILD_TYPE})
endif(NOT CMAKE_BUILD_TYPE)
option(MLC_HIDE_PRIVATE_SYMBOLS "Hide private symbols" ON)
option(MLC_LLM_BUILD_PYTHON_MODULE "Build Python module with scikit-build-core"
OFF)
if(MLC_LLM_INSTALL_STATIC_LIB)
set(BUILD_STATIC_RUNTIME ON)
endif()
set(MLC_VISIBILITY_FLAG "")
if(MLC_HIDE_PRIVATE_SYMBOLS)
set(HIDE_PRIVATE_SYMBOLS ON)
if(NOT MSVC)
set(MLC_VISIBILITY_FLAG "-fvisibility=hidden")
endif()
message(STATUS "Hide private symbols")
endif()
option(BUILD_CPP_TEST "Build cpp unittests" OFF)
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# tvm runtime config: minimize runtime components
set(USE_RPC OFF)
set(USE_MICRO OFF)
set(USE_GRAPH_EXECUTOR OFF)
set(USE_GRAPH_EXECUTOR_DEBUG OFF)
set(USE_AOT_EXECUTOR OFF)
set(USE_PROFILER OFF)
set(USE_GTEST OFF)
set(USE_LIBBACKTRACE OFF)
set(BUILD_DUMMY_LIBTVM ON)
if(NOT DEFINED TVM_SOURCE_DIR)
if(DEFINED ENV{TVM_SOURCE_DIR})
set(TVM_SOURCE_DIR "$ENV{TVM_SOURCE_DIR}")
else()
set(TVM_SOURCE_DIR 3rdparty/tvm)
endif(DEFINED ENV{TVM_SOURCE_DIR})
endif(NOT DEFINED TVM_SOURCE_DIR)
message(STATUS "TVM_SOURCE_DIR: ${TVM_SOURCE_DIR}")
add_subdirectory(${TVM_SOURCE_DIR} tvm EXCLUDE_FROM_ALL)
set(MLC_LLM_RUNTIME_LINKER_LIB "")
set(TOKENZIER_CPP_PATH 3rdparty/tokenizers-cpp)
add_subdirectory(${TOKENZIER_CPP_PATH} tokenizers EXCLUDE_FROM_ALL)
set(XGRAMMAR_PATH 3rdparty/xgrammar)
tvm_file_glob(GLOB_RECURSE MLC_LLM_SRCS cpp/*.cc)
tvm_file_glob(GLOB_RECURSE XGRAMMAR_SRCS ${XGRAMMAR_PATH}/cpp/*.cc)
list(FILTER XGRAMMAR_SRCS EXCLUDE REGEX "${XGRAMMAR_PATH}/cpp/pybind/.*\\.cc")
list(APPEND MLC_LLM_SRCS ${XGRAMMAR_SRCS})
add_library(mlc_llm_objs OBJECT ${MLC_LLM_SRCS})
set(MLC_LLM_INCLUDES
${TVM_SOURCE_DIR}/include ${TVM_SOURCE_DIR}/3rdparty/dlpack/include)
set(MLC_LLM_COMPILE_DEFS ${MLC_LLM_COMPILE_DEFS} __STDC_FORMAT_MACROS=1)
set(MLC_LLM_COMPILE_DEFS ${MLC_LLM_COMPILE_DEFS} XGRAMMAR_ENABLE_LOG_DEBUG=0)
target_compile_definitions(mlc_llm_objs PRIVATE ${MLC_LLM_COMPILE_DEFS})
target_compile_definitions(mlc_llm_objs PRIVATE -DMLC_LLM_EXPORTS)
target_include_directories(mlc_llm_objs PRIVATE ${MLC_LLM_INCLUDES})
target_include_directories(mlc_llm_objs PRIVATE 3rdparty/stb)
target_include_directories(mlc_llm_objs PRIVATE ${TOKENZIER_CPP_PATH}/include)
target_include_directories(mlc_llm_objs PRIVATE ${XGRAMMAR_PATH}/include)
# xgrammar still depends on picojson - use its bundled copy
target_include_directories(mlc_llm_objs
PRIVATE ${XGRAMMAR_PATH}/3rdparty/picojson)
target_link_libraries(mlc_llm_objs PRIVATE tvm_ffi_header)
add_library(mlc_llm SHARED $<TARGET_OBJECTS:mlc_llm_objs>)
add_library(mlc_llm_static STATIC $<TARGET_OBJECTS:mlc_llm_objs>)
add_dependencies(mlc_llm_static tokenizers_cpp sentencepiece-static
tokenizers_c tvm_runtime tvm_runtime_extra)
set_target_properties(mlc_llm_static PROPERTIES OUTPUT_NAME mlc_llm)
target_link_libraries(mlc_llm PUBLIC tvm_runtime)
target_link_libraries(mlc_llm PRIVATE tvm_runtime_extra)
target_link_libraries(mlc_llm PRIVATE tokenizers_cpp)
find_library(FLASH_ATTN_LIBRARY flash_attn
HINTS ${TVM_SOURCE_DIR}/*/3rdparty/libflash_attn/src)
if(FLASH_ATTN_LIBRARY STREQUAL "FLASH_ATTN_LIBRARY-NOTFOUND")
message(
WARNING
"Cannot find libflash_attn. The model must not have been built with --use-flash-attn-mqa option."
)
else()
target_link_libraries(mlc_llm PUBLIC -Wl,--no-as-needed ${FLASH_ATTN_LIBRARY})
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(mlc_llm PRIVATE "TVM_LOG_DEBUG")
target_compile_definitions(mlc_llm_objs PRIVATE "TVM_LOG_DEBUG")
target_compile_definitions(mlc_llm_static PRIVATE "TVM_LOG_DEBUG")
endif()
if(BUILD_CPP_TEST)
message(STATUS "Building cpp unittests")
add_subdirectory(3rdparty/googletest)
file(GLOB_RECURSE MLC_LLM_TEST_SRCS
${PROJECT_SOURCE_DIR}/tests/cpp/*unittest.cc)
add_executable(mlc_llm_cpp_tests ${MLC_LLM_TEST_SRCS})
target_include_directories(mlc_llm_cpp_tests PRIVATE ${MLC_LLM_INCLUDES})
target_include_directories(mlc_llm_cpp_tests
PRIVATE ${PROJECT_SOURCE_DIR}/cpp)
target_include_directories(
mlc_llm_cpp_tests PRIVATE ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
target_link_libraries(mlc_llm_cpp_tests PUBLIC mlc_llm gtest gtest_main)
endif(BUILD_CPP_TEST)
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
target_link_libraries(mlc_llm PRIVATE log)
target_link_libraries(tokenizers_cpp PRIVATE log)
endif()
add_library(mlc_llm_module SHARED $<TARGET_OBJECTS:mlc_llm_objs>)
target_link_libraries(mlc_llm_module PUBLIC tvm_runtime)
target_link_libraries(mlc_llm_module PRIVATE tvm_runtime_extra)
target_link_libraries(mlc_llm_module PRIVATE tokenizers_cpp)
set_property(
TARGET mlc_llm_module
APPEND
PROPERTY LINK_OPTIONS "${MLC_VISIBILITY_FLAG}")
set_property(
TARGET mlc_llm
APPEND
PROPERTY LINK_OPTIONS "${MLC_VISIBILITY_FLAG}")
find_program(CARGO_EXECUTABLE cargo)
if(NOT CARGO_EXECUTABLE)
message(FATAL_ERROR "Cargo is not found! Please install cargo.")
endif()
# when this option is on, we install all static lib deps into lib
if(MLC_LLM_INSTALL_STATIC_LIB)
install(TARGETS mlc_llm_static tokenizers_cpp sentencepiece-static tvm_runtime
tvm_runtime_extra
LIBRARY DESTINATION lib${LIB_SUFFIX})
# tokenizers need special handling as it builds from rust
if(MSVC)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tokenizers/libtokenizers_c.lib
DESTINATION lib${LIB_SUFFIX})
else()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tokenizers/libtokenizers_c.a
DESTINATION lib${LIB_SUFFIX})
endif()
else()
install(
TARGETS tvm_runtime
tvm_runtime_extra
mlc_llm
mlc_llm_module
mlc_llm_static
tokenizers_cpp
sentencepiece-static
RUNTIME_DEPENDENCY_SET
tokenizers_c
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX})
endif()
# Python package installation configuration This section ensures that all
# necessary files are installed for the Python wheel
if(MLC_LLM_BUILD_PYTHON_MODULE)
message(STATUS "Configuring Python package installation")
# Set RPATH for mlc_llm and mlc_llm_module to find other libraries relatively
if(APPLE)
# macOS uses @loader_path
set_target_properties(mlc_llm PROPERTIES INSTALL_RPATH "@loader_path")
set_target_properties(mlc_llm_module PROPERTIES INSTALL_RPATH
"@loader_path")
elseif(LINUX)
# Linux uses $ORIGIN
set_target_properties(mlc_llm PROPERTIES INSTALL_RPATH "\$ORIGIN")
set_target_properties(mlc_llm_module PROPERTIES INSTALL_RPATH "\$ORIGIN")
endif()
# Install compiled shared libraries
install(TARGETS mlc_llm DESTINATION ".")
install(TARGETS mlc_llm_module DESTINATION ".")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/cpp/" DESTINATION "cpp/")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/web/" DESTINATION "web/")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/README.md"
"${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
"${CMAKE_CURRENT_SOURCE_DIR}/NOTICE" DESTINATION ".")
message(STATUS "Python package installation configured")
endif()