cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(kaiming
        DESCRIPTION "kaiming packages"
        HOMEPAGE_URL ""
        LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_BUILD_TYPE "debug")
# 安全编译选项
set(CMAKE_C_FLAGS "$ENV{CFLAGS} -O0 -g -ggdb -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIC -fPIE -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack")
set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -O0 -g -ggdb -std=c++17 -frtti -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIC -fPIE -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack")
# 单元测试编译选项
# set(CMAKE_C_FLAGS "$ENV{CFLAGS} -O0 -g -ggdb -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -fprofile-arcs -ftest-coverage")
# set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -O0 -g -ggdb -std=c++17 -frtti -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -pie")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -pie")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -pie")

find_package(PkgConfig REQUIRED)
find_package(ZLIB REQUIRED)
find_package(Threads REQUIRED)
find_package(nlohmann_json 3.2.0 REQUIRED)

# 使用 REQUIRED, 如果找不到模块，命令将失败并报错，并停止运行
pkg_check_modules(GLIB2 REQUIRED glib-2.0)
pkg_check_modules(GIO2 REQUIRED gio-2.0)
pkg_check_modules(GIO_UNIX2 REQUIRED gio-unix-2.0)
pkg_check_modules(OSTREE REQUIRED ostree-1)
pkg_check_modules(DBUS REQUIRED dbus-1)
pkg_check_modules(DBUSGLIB REQUIRED dbus-glib-1)
pkg_check_modules(CURL REQUIRED libcurl)
pkg_check_modules(UUID REQUIRED uuid)  #  libuuid
pkg_check_modules(LIBELF REQUIRED libelf)

# 输出 libcurl 的库信息（可选）
message("Libcurl include directories: ${CURL_INCLUDE_DIRS}")
message("Libcurl libraries: ${CURL_LIBRARIES}")

set(LOCALEDIR "/opt/system/resource/locale")
configure_file(config.h.in config.h)

aux_source_directory(app SRC_APP)
aux_source_directory(app/builder SRC_APP_BUILDER)
aux_source_directory(app/install SRC_APP_INSTALL)
aux_source_directory(app/update SRC_APP_UPDATE)
aux_source_directory(app/upgrade SRC_APP_UPGRADE)
aux_source_directory(app/list SRC_APP_LIST)
aux_source_directory(app/info SRC_APP_INFO)
aux_source_directory(app/search SRC_APP_SEARCH)
aux_source_directory(app/repair SRC_APP_REPAIR)
aux_source_directory(app/uninstall SRC_APP_UNINSTALL)
aux_source_directory(app/enter SRC_APP_ENTER)
aux_source_directory(app/run SRC_APP_RUN)
aux_source_directory(app/ps SRC_APP_PS)
aux_source_directory(app/kill SRC_APP_KILL)
aux_source_directory(app/which SRC_APP_WHICH)
aux_source_directory(app/remoteModify SRC_APP_REMOTE)
aux_source_directory(dbus SRC_APP_DBUS)
aux_source_directory(common SRC_COMMON)

add_library(kaiming-common
    OBJECT
        ${SRC_APP_INSTALL}
        ${SRC_APP_ENTER}
        ${SRC_APP_UPDATE}
        ${SRC_APP_UPGRADE}
        ${SRC_APP_LIST}
        ${SRC_APP_SEARCH}
        ${SRC_APP_INFO}
        ${SRC_APP_REPAIR}
        ${SRC_APP_UNINSTALL}
        ${SRC_APP_RUN}
        ${SRC_APP_PS}
        ${SRC_APP_KILL}
        ${SRC_APP_WHICH}
        ${SRC_APP_REMOTE}
        ${SRC_COMMON}
)
set_target_properties(kaiming-common
    PROPERTIES
        POSITION_INDEPENDENT_CODE 1
)

add_executable(kaiming
    ${SRC_APP}
    ${SRC_APP_BUILDER}
    #${SRC_APP_ENTER}
    $<TARGET_OBJECTS:kaiming-common>
)

# 增加系统dbus
add_executable(kaiming-system-dbus
    ./dbus/gdbus/KMSystemServerAdaptor.cpp
    $<TARGET_OBJECTS:kaiming-common>
)

# 增加Session dbus
add_executable(kaiming-sessionproxy-dbus
    ./dbus/gdbus/KMSessionProxy.cpp
    ./common/KMLogger.cpp
)

# 增加SystemAsync dbus
add_executable(kaiming-systemproxy-dbus
    ./dbus/gdbus/KMSystemProxy.cpp
    ./common/KMLogger.cpp
)

add_dependencies(kaiming-system-dbus build_kmsysteminterface)
add_dependencies(kaiming-sessionproxy-dbus build_kmsessionproxy)
add_dependencies(kaiming-systemproxy-dbus build_kmsystemproxy)

target_include_directories(kaiming-common PUBLIC
    ${GLIB2_INCLUDE_DIRS}
    ${GIO2_INCLUDE_DIRS}
    ${GIO_UNIX2_INCLUDE_DIRS}
    ${OSTREE_INCLUDE_DIRS}
    ${DBUSCPP_INCLUDE_DIRS}
    ${DBUS_INCLUDE_DIRS}
    ${XAU_INCLUDE_DIRS}
    ${CURL_INCLUDE_DIRS}
    ${LIBELF_INCLUDE_DIRS}
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${nlohmann_json_INCLUDE_DIRS})

target_include_directories(kaiming PRIVATE
    ${GLIB2_INCLUDE_DIRS}
    ${GIO2_INCLUDE_DIRS}
    ${GIO_UNIX2_INCLUDE_DIRS}
    ${OSTREE_INCLUDE_DIRS}
    ${DBUSCPP_INCLUDE_DIRS}
    ${DBUS_INCLUDE_DIRS}
    ${XAU_INCLUDE_DIRS}
    ${CURL_INCLUDE_DIRS}
    ${LIBELF_INCLUDE_DIRS}
    ${CMAKE_CURRENT_SOURCE_DIR})

target_include_directories(kaiming-system-dbus PUBLIC
    ${GLIB2_INCLUDE_DIRS}
    ${GIO2_INCLUDE_DIRS}
    ${GIO_UNIX2_INCLUDE_DIRS}
    ${OSTREE_INCLUDE_DIRS}
    ${DBUSCPP_INCLUDE_DIRS}
    ${DBUS_INCLUDE_DIRS}
    ${XAU_INCLUDE_DIRS}
    ${CURL_INCLUDE_DIRS}
    ${LIBELF_INCLUDE_DIRS}
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${GLIB_INCLUDE_DIRS}
)

target_include_directories(kaiming-sessionproxy-dbus PUBLIC
    ${GIO_UNIX2_INCLUDE_DIRS}
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${GLIB_INCLUDE_DIRS}
)

target_include_directories(kaiming-systemproxy-dbus PUBLIC
    ${GIO_UNIX2_INCLUDE_DIRS}
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${GLIB_INCLUDE_DIRS}
)

target_link_libraries(kaiming-common PUBLIC
    ${GLIB2_LIBRARIES}
    ${GIO2_LIBRARIES}
    ${GIO_UNIX2_LIBRARIES}
    ${OSTREE_LIBRARIES}
    ${DBUSCPP_LIBRARIES}
    ${XAU_LIBRARIES}
    ${CURL_LIBRARIES}
    ${ZLIB_LIBRARIES}
    ${UUID_LIBRARIES}  # 链接 libuuid
    Threads::Threads
    -lstdc++fs
    ${LIBELF_LIBRARIES}
    -lelf
)

target_link_libraries(kaiming PRIVATE
    ${GLIB2_LIBRARIES}
    ${GIO2_LIBRARIES}
    ${GIO_UNIX2_LIBRARIES}
    ${OSTREE_LIBRARIES}
    ${DBUSCPP_LIBRARIES}
    ${XAU_LIBRARIES}
    ${CURL_LIBRARIES}
    ${ZLIB_LIBRARIES}
    ${UUID_LIBRARIES}
    Threads::Threads
    -lstdc++fs 
    ${LIBELF_LIBRARIES}
    -lelf
)

target_link_libraries(kaiming-system-dbus PRIVATE
    ${GLIB2_LIBRARIES}
    ${GIO2_LIBRARIES}
    ${GIO_UNIX2_LIBRARIES}
    ${OSTREE_LIBRARIES}
    ${DBUSCPP_LIBRARIES}
    ${XAU_LIBRARIES}
    ${CURL_LIBRARIES}
    ${ZLIB_LIBRARIES}
    ${UUID_LIBRARIES}
    Threads::Threads
    -lstdc++fs
    ${LIBELF_LIBRARIES}
    -lelf
    ${CMAKE_BINARY_DIR}/dbus/kmsysteminterface.a
    ${GLIB_LIBRARIES}
)

target_link_libraries(kaiming-sessionproxy-dbus PRIVATE
    ${GIO_UNIX2_LIBRARIES}
    ${CMAKE_BINARY_DIR}/dbus/kmsessionproxy.a
    ${GLIB_LIBRARIES}
)

target_link_libraries(kaiming-systemproxy-dbus PRIVATE
    ${GIO_UNIX2_LIBRARIES}
    ${CMAKE_BINARY_DIR}/dbus/kmsystemproxy.a
    ${GLIB_LIBRARIES}
)

# set(ETC_PATH "/opt/system/conf")
set(ETC_PATH "/etc")
set(LIB_PATH "/opt/system/lib")
set(USR_SHARE_PATH "/opt/system/resource")
execute_process(COMMAND dbusxx-xml2cpp ${CMAKE_CURRENT_SOURCE_DIR}/data/org.freedesktop.kaiming.xml --proxy=${CMAKE_CURRENT_SOURCE_DIR}/common/KMDbusProxy.h --adaptor=${CMAKE_CURRENT_SOURCE_DIR}/common/KMDbusAdptor.h)
# execute_process(COMMAND dbusxx-xml2cpp ${CMAKE_CURRENT_SOURCE_DIR}/dbus/kmsysteminterface.xml  --adaptor=${CMAKE_CURRENT_SOURCE_DIR}/dbus/autogenserveradaptor.h)
#execute_process(COMMAND dbusxx-xml2cpp ${CMAKE_CURRENT_SOURCE_DIR}/dbus/kmsessioninterface.xml  --adaptor=${CMAKE_CURRENT_SOURCE_DIR}/dbus/KMSessionServerAdaptor.h)

# 安装二进制到 /opt/kaiming-tools/bin
install( TARGETS kaiming
    RUNTIME DESTINATION  /opt/kaiming-tools/bin
)


# 安装二进制到 /opt/kaiming-tools/bin
install( TARGETS kaiming-system-dbus
    RUNTIME DESTINATION  /opt/kaiming-tools/bin
)

# 安装二进制到 /opt/kaiming-tools/bin
install( TARGETS kaiming-sessionproxy-dbus
    RUNTIME DESTINATION  /opt/kaiming-tools/bin
)

install( TARGETS kaiming-systemproxy-dbus
    RUNTIME DESTINATION  /opt/kaiming-tools/bin
)

# 安装 run 运行所需文件，没有则会开启 dbus 失败
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/
        USE_SOURCE_PERMISSIONS
        DESTINATION ${ETC_PATH}/systemd/system-environment-generators
        FILES_MATCHING PATTERN "60-kaiming"
)

# 安装 system dbus 运行所需文件，没有则会开启 dbus 失败
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kylin.kaiming.conf
        DESTINATION ${ETC_PATH}/dbus-1/system.d
)

# 安装 system dbus 运行所需文件，没有则会开启 dbus 失败
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kylin.kaiming.service
        DESTINATION ${LIB_PATH}/systemd/system
)

# 安装 session dbus 运行所需文件，没有则会开启 dbus 失败
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kaiming.session.proxy.conf
        DESTINATION ${ETC_PATH}/dbus-1/session.d
)

# 安装 session dbus systemd运行所需文件，没有则会开启 dbus 失败
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kaiming.sessionsystemd.proxy.service
        DESTINATION ${LIB_PATH}/systemd/user
)

# 安装 session dbus 运行所需文件，没有则会开启 dbus 失败
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kaiming.session.proxy.service
        DESTINATION ${USR_SHARE_PATH}/dbus-1/services
)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kylin.kaiming.policy
    DESTINATION ${USR_SHARE_PATH}/polkit-1/actions
)

# 安装 session dbus 运行所需文件，没有则会开启 dbus 失败
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kaiming.system.proxy.conf
        DESTINATION ${ETC_PATH}/dbus-1/system.d
)

# 安装 session dbus systemd运行所需文件，没有则会开启 dbus 失败
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/org.kaiming.systemproxy.service
        DESTINATION ${LIB_PATH}/systemd/system
)

# 安装 XDG_DATA_DIRS 环境变量设置脚本
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/20kaiming
        DESTINATION ${ETC_PATH}/X11/Xsession.d
)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/kaiming.sh
        DESTINATION ${ETC_PATH}/profile.d
)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/60-kaimingenv.conf
        DESTINATION ${ETC_PATH}/ostree/ostree.conf.d
)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/kaiming-system-systemd.conf
        DESTINATION ${ETC_PATH}/systemd/system.conf.d
)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/kaiming-user-systemd.conf
        DESTINATION ${ETC_PATH}/systemd/user.conf.d
)

# 生成自启服务软链接
# execute_process(COMMAND systemctl enable org.kylin.kaiming.service)

# 安装 kaiming 命令补全脚本
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/shells/kaiming_completion.sh
        DESTINATION ${ETC_PATH}/bash_completion.d
)

# 安装 kaiming-custom.xml
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/doc/kaiming-custom.xml
        DESTINATION ${USR_SHARE_PATH}/mime/packages/
)

# execute_process(COMMAND chmod +x /etc/bash_completion.d/kaiming_completion.sh)

# 安装 kaiming 版本检查脚本
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/shells/kaiming_version.sh
        DESTINATION /opt/kaiming-tools/bin
)

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/shells/install_files.sh
        DESTINATION /opt/kaiming-tools/bin
)

#  安装 crun 分离检查脚本
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/shells/start.sh
        PERMISSIONS
        OWNER_READ OWNER_WRITE OWNER_EXECUTE
        GROUP_READ GROUP_EXECUTE
        WORLD_READ WORLD_EXECUTE
        DESTINATION /opt/kaiming-tools/bin
)

# 安装dbus客户端
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/shells/dbus-cli.sh
        PERMISSIONS
        OWNER_READ OWNER_WRITE OWNER_EXECUTE
        GROUP_READ GROUP_EXECUTE
        WORLD_READ WORLD_EXECUTE
        DESTINATION /opt/kaiming-tools/bin
)

# 安装 trigger 脚本，并保留权限
# References: https://cmake.org/cmake/help/v2.8.10/cmake.html#command%3ainstall
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/shells
        USE_SOURCE_PERMISSIONS
        DESTINATION /opt/kaiming-tools/share/kaiming
        FILES_MATCHING PATTERN "*.trigger"
)

# 安装其他文件
# if(NOT EXISTS "/opt/kaiming/repo")
#     file(MAKE_DIRECTORY /opt/kaiming)
#     install(DIRECTORY data/repo DESTINATION /opt/kaiming/)
# endif()

# 设置 PO 文件和目标 MO 文件的路径
# set(POT_FILE ${CMAKE_SOURCE_DIR}/po/kaiming.pot)
set(PO_FILE ${CMAKE_SOURCE_DIR}/po/kaiming.po)
set(MO_FILE ${CMAKE_SOURCE_DIR}/po/kaiming.mo)  # 在构建目录下生成 .mo 文件

# 需要添加翻译的文件
# set(SOURCE_FILE ../app/builder/KMBuildExport.cpp) 

# # 生成pot
# add_custom_command(
#     # generate_pot
#     OUTPUT ${POT_FILE}
#     COMMAND xgettext -k_ --from-code=UTF-8 -o ${POT_FILE} ${SOURCE_FILE}
#     DEPENDS ${SOURCE_FILE}
#     COMMENT "Generating ${POT_FILE}"
# )

# # 更新po,文件添加需要新翻译的内容时使用
# add_custom_command(
#     OUTPUT ${PO_FILE}
#     COMMAND msgmerge -U ${PO_FILE} ${POT_FILE}
#     DEPENDS ${POT_FILE}
#     COMMENT "Generating ${PO_FILE}"
# )

# 添加自定义命令，将 .po 文件转换为 .mo 文件
add_custom_command(
    OUTPUT ${MO_FILE}  # 输出的 .mo 文件
    COMMAND msgfmt --output-file ${MO_FILE} ${PO_FILE}  # msgfmt 转换命令
    DEPENDS ${PO_FILE}  # 声明 .mo 文件依赖于 .po 文件
    COMMENT "Converting PO to MO file"  # 转换注释
    VERBATIM  # 保证命令中的空格问题
)

# 创建自定义目标，确保在构建时生成 .mo 文件
add_custom_target(
    po_to_mo ALL  # 将此目标设置为构建时自动执行
    DEPENDS ${MO_FILE}  # 依赖于生成的 .mo 文件
)

# 安装 .mo 文件到指定的系统目录
install(
    FILES ${MO_FILE}  # 安装生成的 .mo 文件
    DESTINATION ${USR_SHARE_PATH}/locale/zh_CN/LC_MESSAGES  # 安装路径

)

# 本地安装时
install(
    CODE "execute_process(COMMAND sh ${CMAKE_SOURCE_DIR}/shells/install_files.sh)"
)
#删除生成的mo文件
install(
    CODE "file(REMOVE \"${MO_FILE}\")"
)

add_subdirectory(dbus)
add_subdirectory(ok)
# add_subdirectory(test/cpptest)
