cmake_minimum_required(VERSION 3.27)

# Roots
include("../roots.cmake")

set(CONTEXT Robot_V2.Release+GD32C103CB)
set(TARGET ${CONTEXT})
set(OUT_DIR "${SOLUTION_ROOT}/out/Robot_V2/GD32C103CB/Release")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(HEX_FILE "Robot_V2.hex")
set(LD_MAP_FILE "Robot_V2.axf.map")
set(LD_SCRIPT "${SOLUTION_ROOT}/Robot_V2/RTE/Device/GD32C103CB/ac6_linker_script.sct.src")
set(LD_REGIONS "${SOLUTION_ROOT}/Robot_V2/RTE/Device/GD32C103CB/regions_GD32C103CB.h")
set(LD_SCRIPT_PP "${CMAKE_CURRENT_BINARY_DIR}/ac6_linker_script.sct")

# Processor Options
set(CPU Cortex-M4)
set(FPU SP_FPU)
set(BYTE_ORDER Little-endian)

# Toolchain config map
include("toolchain.cmake")

# Setup project
project(${CONTEXT} LANGUAGES CXX C ASM)

# Compilation database
add_custom_target(database
  COMMAND ${CMAKE_COMMAND} -E make_directory "${OUT_DIR}"
  COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" "${OUT_DIR}"
)
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})

# Setup context
add_executable(${CONTEXT})
set_target_properties(${CONTEXT} PROPERTIES PREFIX "" SUFFIX ".axf" OUTPUT_NAME "Robot_V2")
set_target_properties(${CONTEXT} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUT_DIR})
add_library(${CONTEXT}_GLOBAL INTERFACE)

# Includes
target_include_directories(${CONTEXT} PUBLIC
  "${SOLUTION_ROOT}/Robot_V2/RTE/_Release_GD32C103CB"
  "${CMSIS_PACK_ROOT}/ARM/CMSIS/4.5.0/CMSIS/Include"
  "${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc"
  "${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Include"
  "${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Utilities"
  "${SOLUTION_ROOT}/Robot_V2"
  "${SOLUTION_ROOT}/Robot_V2/sys"
  "${SOLUTION_ROOT}/Robot_V2/device"
)

# Defines
target_compile_definitions(${CONTEXT} PUBLIC
  $<$<COMPILE_LANGUAGE:C,CXX>:
    GD32C10x
    _RTE_
  >
)

# Compile options
target_compile_options(${CONTEXT} PUBLIC
  $<$<COMPILE_LANGUAGE:ASM>:
    "SHELL:${ASM_CPU}"
    "SHELL:${ASM_FLAGS}"
    "SHELL:${ASM_BYTE_ORDER}"
    "SHELL:-D__packed=packed"
    "SHELL:-D__MICROLIB"
    "SHELL:-gdwarf-5"
    "SHELL:-masm=auto"
  >
  $<$<COMPILE_LANGUAGE:C>:
    "SHELL:${CC_CPU}"
    "SHELL:${CC_FLAGS}"
    "SHELL:${CC_BYTE_ORDER}"
    "SHELL:-D__packed=packed"
    "SHELL:-fshort-enums"
    "SHELL:-fshort-wchar"
    "SHELL:-D__MICROLIB"
    "SHELL:-Wno-register"
    "SHELL:-gdwarf-5"
    "SHELL:-std=gnu11"
    "SHELL:-Wno-macro-redefined"
    "SHELL:-Wno-pragma-pack"
    "SHELL:-Wno-parentheses-equality"
    "SHELL:-Wno-license-management"
  >
  $<$<COMPILE_LANGUAGE:CXX>:
    "SHELL:${CXX_CPU}"
    "SHELL:${CXX_FLAGS}"
    "SHELL:${CXX_BYTE_ORDER}"
    "SHELL:-fshort-enums"
    "SHELL:-fshort-wchar"
    "SHELL:-D__MICROLIB"
    "SHELL:-Wno-register"
    "SHELL:-gdwarf-5"
    "SHELL:-Wno-macro-redefined"
    "SHELL:-Wno-pragma-pack"
    "SHELL:-Wno-parentheses-equality"
    "SHELL:-Wno-license-management"
  >
)

# Compile Options Abstractions
add_library(${CONTEXT}_ABSTRACTIONS INTERFACE)
cbuild_set_options_flags(CXX "balanced" "off" "" "" CXX_OPTIONS_FLAGS_${CONTEXT})
cbuild_set_options_flags(CC "balanced" "off" "" "" CC_OPTIONS_FLAGS_${CONTEXT})
cbuild_set_options_flags(ASM "balanced" "off" "" "" ASM_OPTIONS_FLAGS_${CONTEXT})
target_compile_options(${CONTEXT}_ABSTRACTIONS INTERFACE
  $<$<COMPILE_LANGUAGE:CXX>:
    "SHELL:${CXX_OPTIONS_FLAGS_${CONTEXT}}"
  >
  $<$<COMPILE_LANGUAGE:C>:
    "SHELL:${CC_OPTIONS_FLAGS_${CONTEXT}}"
  >
  $<$<COMPILE_LANGUAGE:ASM>:
    "SHELL:${ASM_OPTIONS_FLAGS_${CONTEXT}}"
  >
)

# Add groups and components
include("groups.cmake")
include("components.cmake")

target_link_libraries(${CONTEXT} PUBLIC
  Group_Source_Files
  Group_sys
  Group_device
  ARM_CMSIS_CORE_4_3_0
  GigaDevice_Device_EVAL_GD32C10x_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_CAN_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_CRC_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_DBG_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_DMA_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_EXTI_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_FMC_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_FWDGT_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_GPIO_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_MISC_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_PMU_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_RCU_1_0_0
  GigaDevice_Device_GD32C10x_StdPeripherals_USART_1_0_0
  GigaDevice_Device_GD32C10x_libopt_1_0_0
  GigaDevice_Device_Startup_1_0_0
)

# Linker options
target_link_options(${CONTEXT} PUBLIC
  "SHELL:${LD_CPU}"
  "SHELL:${_LS}\"${LD_SCRIPT_PP}\""
  "SHELL:${LD_MAP}"
  "SHELL:--library_type=microlib"
  "SHELL:--entry=Reset_Handler"
  "SHELL:--info=summarysizes"
  "SHELL:--summary_stderr"
  "SHELL:--diag_suppress=L6314W"
)
set(LD_DEPS ${LD_SCRIPT} ${LD_REGIONS})
set_target_properties(${CONTEXT} PROPERTIES LINK_DEPENDS "${LD_DEPS}")

# Linker script pre-processing
add_custom_command(TARGET ${CONTEXT} PRE_LINK COMMAND ${CPP} ARGS ${CPP_ARGS_LD_SCRIPT} BYPRODUCTS ${LD_SCRIPT_PP})

# Hex Conversion
 add_custom_command(TARGET ${CONTEXT} POST_BUILD COMMAND ${CMAKE_OBJCOPY} ${ELF2HEX})
