#to compile the project:
# mkdir _build
# cd _build
# cmake -D CMAKE_TOOLCHAIN_FILE=../benchmark/compiler.cmake ..
# make
# make flash
cmake_minimum_required(VERSION 3.5)

# with this option, cmake will not try to compile a 
# simple test program (that may fail for an embedded target)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")

#project name
project(benchmark_exe)
enable_language(C CXX ASM)


set(TRAMPOLINE_BASE_PATH ${CMAKE_SOURCE_DIR}/../../../)
set(TRAMPOLINE_MACHINE_PATH ${TRAMPOLINE_BASE_PATH}/machines)
set(TRAMPOLINE_GOIL_TEMPLATES ${TRAMPOLINE_BASE_PATH}/goil/templates)
set(APP_GENERATED_PATH ${CMAKE_SOURCE_DIR}/benchmark)

#goil
set(OILFILE ${CMAKE_SOURCE_DIR}/benchmark.oil)
set(OILCOMPILER goil)
set(OILFLAGS -t=renesas/g4mh --templates=${TRAMPOLINE_GOIL_TEMPLATES})

#cross compiler
include("benchmark/compiler.cmake")

set(CFLAGS #CFLAGS
	#C flags from .oil file
	-Xcpu=g4mh -g -g_line -Xfxu=off -Xasm_path=.
	 -Xfloat=soft -Xdbl_size=8 -Xround=nearest
	-DTIME=TIME
	-Ospeed -Oinline_size
	-I../coremark -I../coremark/barebones -DITERATIONS=30000
)

set(PRECFLAGS #PRE CFLAGS
)

set(CXXFLAGS #C++ FLAGS
)

set(PRECXXFLAGS #PRE C++ FLAGS
)

set(COMMONFLAGS #COMMON FLAGS (C/C++/ASM)
)

set(PRECOMMONFLAGS #PRE COMMON FLAGS (C/C++/ASM)
)

add_compile_options(
  ${PRECOMMONFLAGS}
  ${COMMONFLAGS}
  "$<$<COMPILE_LANGUAGE:C>:${PRECFLAGS}>"
  "$<$<COMPILE_LANGUAGE:C>:${CFLAGS}>"
  "$<$<COMPILE_LANGUAGE:CXX>:${PRECXXFLAGS}>"
  "$<$<COMPILE_LANGUAGE:CXX>:${CXXFLAGS}>"
  "$<$<COMPILE_LANGUAGE:ASM>:${PRECFLAGS}>"
  "$<$<COMPILE_LANGUAGE:ASM>:${CFLAGS}>"
)

#Application sources
set(APP_SRCS
	#--- C files of the application
	benchmark.c
	dhrystone/dhry_1.c
	dhrystone/dhry_2.c
	coremark/barebones/core_portme.c
	coremark/core_list_join.c
	coremark/core_main.c
	coremark/core_matrix.c
	coremark/core_state.c
	coremark/core_util.c
)

#Trampoline kernel sources 
set(TRAMPOLINE_OS_SRCS
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_kernel.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_timeobj_kernel.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_action.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_error.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_os_kernel.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_os.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_interrupt_kernel.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_task_kernel.c
	${TRAMPOLINE_BASE_PATH}/os/tpl_os_resource_kernel.c
) 

#Trampoline generated files
set(APP_GENERATED_SRCS
	#os generated files
	${APP_GENERATED_PATH}/tpl_app_config.c
	${APP_GENERATED_PATH}/tpl_dispatch_table.c
	${APP_GENERATED_PATH}/tpl_invoque.c
)

#Trampoline target dependant files
set(TRAMPOLINE_MACHINE_SRCS
	${TRAMPOLINE_MACHINE_PATH}/renesas/tpl_machine_renesas.c
	${TRAMPOLINE_MACHINE_PATH}/renesas/renesas_irq.c
	${TRAMPOLINE_MACHINE_PATH}/renesas/cstart0.asm
	${TRAMPOLINE_MACHINE_PATH}/renesas/tpl_startup.asm
	${TRAMPOLINE_MACHINE_PATH}/renesas/tpl_sc_handler.asm
	${TRAMPOLINE_MACHINE_PATH}/renesas/tpl_irq_handler.asm
)

# Trampoline target library sources (drivers)
set(TARGET_LIBRARY_SRCS
)

#Include directories
include_directories(
	${TRAMPOLINE_BASE_PATH}/autosar
	${TRAMPOLINE_BASE_PATH}/com
	${TRAMPOLINE_BASE_PATH}/debug
	${TRAMPOLINE_BASE_PATH}/ioc
	${TRAMPOLINE_BASE_PATH}/os
	${TRAMPOLINE_MACHINE_PATH}/renesas
	benchmark
)

#Executable (should be defined after compile options)
add_executable(${PROJECT_NAME} 
    ${APP_SRCS}
    ${TRAMPOLINE_OS_SRCS}
    ${APP_GENERATED_SRCS}
	${TARGET_LIBRARY_SRCS}
    ${TRAMPOLINE_MACHINE_SRCS}
)

#Linker
set(LINKER_DIR ${APP_GENERATED_PATH})

set(LINKER_FLAGS 
	#linker flags from target options
	#linker flags from .oil file
	-debug -nocompress -NOOPtimize -memory=high -nologo -SHow=ALL
)

#
function(add_gcc_library libCmd)
  #use gcc to get the full path to libs (libgcc, libc)
  execute_process(
    COMMAND ${CMAKE_C_COMPILER} ${PRECOMMONFLAGS} ${PRECFLAGS} ${COMMONFLAGS} ${CFLAGS} ${libCmd}
    RESULT_VARIABLE returnValue
    OUTPUT_VARIABLE full_lib_path
    OUTPUT_STRIP_TRAILING_WHITESPACE)

  if (${returnValue} EQUAL 0)
    #ok, now extract only the directory
    get_filename_component(libgcc_path ${full_lib_path} DIRECTORY)
    set(libpath ${libgcc_path} PARENT_SCOPE)
  else()
    message("library ${libCmd} not found!")
  endif()
endfunction()

if(${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
	add_gcc_library("-print-libgcc-file-name") #try to find libgcc
	list(APPEND LINKER_FLAGS -L${libpath} -lgcc)
	add_gcc_library("-print-file-name=libc.a") #try to find libc
	list(APPEND LINKER_FLAGS -L${libpath} -lc)
endif()

#should be defined after 'add_executable'
target_link_libraries(${PROJECT_NAME}
	${LINKER_FLAGS}
)



#post build commands (bin file, flash, …)


#TODO: add alias avec dependance.
#add_custom_target(burn
#    DEPENDS flash
#)

cmake_path(RELATIVE_PATH OILFILE OUTPUT_VARIABLE OILFILE_REL)
cmake_path(RELATIVE_PATH TRAMPOLINE_GOIL_TEMPLATES OUTPUT_VARIABLE TRAMPOLINE_GOIL_TEMPLATES_REL)
set(OILFLAGS_REL -t=renesas/g4mh --templates=${TRAMPOLINE_GOIL_TEMPLATES_REL})

#goil (will update generated files, and depends on .oil input file)
add_custom_command(OUTPUT ${APP_GENERATED_SRCS} 
    DEPENDS ${OILFILE}
    COMMAND ${OILCOMPILER} ${OILFLAGS_REL} ${OILFILE_REL}
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} #build dir
    COMMENT "call Goil (.oil to code source)"
)