cmake_minimum_required(VERSION 3.20)
project(l_lang C)

set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)

# === LLVM 配置 ===
set(LLVM_PREFIX "D:/settings/Language/LLVM" CACHE PATH "LLVM installation prefix")

# 查找 LLVM（优先使用 CONFIG 模式，失败则手动配置）
find_package(LLVM 19 QUIET CONFIG
    HINTS ${LLVM_PREFIX}/lib/cmake/llvm
          ${LLVM_PREFIX}/cmake
)

if(NOT LLVM_FOUND)
    message(STATUS "LLVM CONFIG not found — using manual LLVM paths")
    set(LLVM_FOUND TRUE)
    set(LLVM_INCLUDE_DIRS "${LLVM_PREFIX}/include")
    set(LLVM_LIBRARY_DIR "${LLVM_PREFIX}/lib")
    set(LLVM_LIBRARIES "${LLVM_PREFIX}/lib/LLVM-C.lib")
    # 标记使用手动模式
    set(LLVM_MANUAL_MODE ON)
else()
    message(STATUS "LLVM found: ${LLVM_DIR}")
    message(STATUS "LLVM includes: ${LLVM_INCLUDE_DIRS}")
    message(STATUS "LLVM available libs: ${LLVM_AVAILABLE_LIBS}")
    set(LLVM_MANUAL_MODE OFF)
endif()

# === 编译器库（不含 main.c，供测试复用）===
file(GLOB_RECURSE L_LANG_LIB_SOURCES "src/*.c")
list(REMOVE_ITEM L_LANG_LIB_SOURCES "${CMAKE_SOURCE_DIR}/src/driver/main.c")

add_library(l_lang_lib STATIC ${L_LANG_LIB_SOURCES})
target_include_directories(l_lang_lib PRIVATE
    ${CMAKE_SOURCE_DIR}/include
    ${LLVM_INCLUDE_DIRS}
    src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
)
target_compile_options(l_lang_lib PRIVATE -Wall -Wextra -g)

# === 编译器可执行文件 ===
add_executable(l_lang src/driver/main.c)
target_link_libraries(l_lang PRIVATE l_lang_lib)
target_include_directories(l_lang PRIVATE
    ${CMAKE_SOURCE_DIR}/include
    ${LLVM_INCLUDE_DIRS}
    src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
)

# === 链接 LLVM（通过库）===
if(LLVM_MANUAL_MODE)
    target_link_libraries(l_lang_lib PUBLIC ${LLVM_LIBRARIES})
    message(STATUS "Linking LLVM manually: ${LLVM_LIBRARIES}")
else()
    target_link_libraries(l_lang_lib PUBLIC LLVM)
endif()

# === LLVM 定义 ===
if(NOT LLVM_MANUAL_MODE)
    target_compile_definitions(l_lang_lib PRIVATE ${LLVM_DEFINITIONS})
endif()

# === 测试可执行文件（每个测试文件独立编译，各有自己的 main）===
# Parser 测试
add_executable(l_lang_test test/test_parser.c)
target_link_libraries(l_lang_test PRIVATE l_lang_lib)
target_include_directories(l_lang_test PRIVATE
    ${CMAKE_SOURCE_DIR}/include
    ${LLVM_INCLUDE_DIRS}
    src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
    test
)

# Lexer 测试
add_executable(l_lang_lexer_test test/test_lexer.c)
target_link_libraries(l_lang_lexer_test PRIVATE l_lang_lib)
target_include_directories(l_lang_lexer_test PRIVATE
    ${CMAKE_SOURCE_DIR}/include
    ${LLVM_INCLUDE_DIRS}
    src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
    test
)

# Sema 测试
add_executable(l_lang_sema_test test/test_sema.c)
target_link_libraries(l_lang_sema_test PRIVATE l_lang_lib)
target_include_directories(l_lang_sema_test PRIVATE
    ${CMAKE_SOURCE_DIR}/include
    ${LLVM_INCLUDE_DIRS}
    src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
    test
)

# Codegen 测试
add_executable(l_lang_codegen_test test/test_codegen.c)
target_link_libraries(l_lang_codegen_test PRIVATE l_lang_lib)
target_include_directories(l_lang_codegen_test PRIVATE
    ${CMAKE_SOURCE_DIR}/include
    ${LLVM_INCLUDE_DIRS}
    src/util src/lexer src/ast src/parser src/sema src/codegen src/driver
    test
)
