set_property(GLOBAL APPEND_STRING PROPERTY testprog_cflags "-g -O0")

# Check and add CFLAG to testprog_cflags
include(CheckCCompilerFlag)
function(test_and_add_testprog_cflag flag)
  # We need unique variable name since check_c_compiler_flag caches results
  string(MAKE_C_IDENTIFIER "HAVE_FLAG_${flag}" flag_var)
  check_c_compiler_flag("${flag}" ${flag_var})
  if(${${flag_var}})
    set_property(GLOBAL APPEND_STRING PROPERTY testprog_cflags " ${flag}")
  else()
    message(STATUS "${CMAKE_C_COMPILER} does not support ${flag}")
  endif()
endfunction()

test_and_add_testprog_cflag("-fno-omit-frame-pointer")
test_and_add_testprog_cflag("-mno-omit-leaf-frame-pointer")
get_property(testprog_cflags GLOBAL PROPERTY testprog_cflags)

file(GLOB testprog_sources CONFIGURE_DEPENDS *.c *.cpp)
set(testprogtargets "")
function(testprog_compile is_pie)
  foreach(testprog_source ${testprog_sources})
    get_filename_component(testprog_name ${testprog_source} NAME_WE)
    set(extra_cflags "")
    set(ldflags "-no-pie")
    if(is_pie)
      set(testprog_name "${testprog_name}-pie")
      set(extra_cflags "-fpie")
      set(ldflags "-pie")
    endif()
    add_executable(${testprog_name} ${testprog_source})
    set_target_properties(${testprog_name}
      PROPERTIES
        LINK_SEARCH_START_STATIC FALSE
        LINK_SEARCH_END_STATIC FALSE
        COMPILE_FLAGS "${testprog_cflags} ${extra_cflags}"
        LINK_FLAGS "${ldflags}")
    target_include_directories(${testprog_name} PRIVATE ${CMAKE_SOURCE_DIR}/tests/include)
    list(APPEND testprogtargets ${testprog_name})
  endforeach()
endfunction()
# Compile all test programs into PIE and non-PIE ELF executables.
testprog_compile(FALSE)
testprog_compile(TRUE)

find_program(GO_EXECUTABLE go)
if(GO_EXECUTABLE)
  file(GLOB testprog_go_sources CONFIGURE_DEPENDS *.go)
  foreach(testprog_source ${testprog_go_sources})
    get_filename_component(testprog_name ${testprog_source} NAME_WE)
    add_custom_command(
      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${testprog_name}
      COMMAND ${GO_EXECUTABLE} build -o ${CMAKE_CURRENT_BINARY_DIR}/${testprog_name} ${testprog_source}
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      DEPENDS ${testprog_source}
    )
    list(APPEND testprogtargets ${testprog_name})
  endforeach()
endif()

find_program(RUSTC_EXECUTABLE rustc)
if(RUSTC_EXECUTABLE)
  file(GLOB testprog_rust_sources CONFIGURE_DEPENDS *.rs)
  foreach(testprog_source ${testprog_rust_sources})
    get_filename_component(testprog_name ${testprog_source} NAME_WE)
    add_custom_command(
      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${testprog_name}
      COMMAND ${RUSTC_EXECUTABLE} -C symbol_mangling_version=v0 -o ${CMAKE_CURRENT_BINARY_DIR}/${testprog_name} ${testprog_source}
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      DEPENDS ${testprog_source}
    )
    list(APPEND testprogtargets ${testprog_name})
  endforeach()
endif()

add_custom_target(testprogs ALL DEPENDS ${testprogtargets})

foreach(prog usdt_lib usdt_lib-pie)
  target_include_directories(${prog} PRIVATE ${CMAKE_SOURCE_DIR}/tests/testlibs/)
  target_compile_options(${prog} PRIVATE -fPIC)
  target_link_libraries(${prog} usdt_tp)
endforeach()
