
function(add_diff_binary target_name)
  cmake_parse_arguments(
    "DIFF"
    "" # No optional arguments
    "SUITE" # Single value arguments
    "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi-value arguments
    ${ARGN}
  )
  if(NOT DIFF_SRCS)
    message(FATAL_ERROR "'add_diff_binary' target requires a SRCS list of .cpp "
                        "files.")
  endif()
  if(NOT DIFF_DEPENDS)
    message(FATAL_ERROR "'add_diff_binary' target requires a DEPENDS list of "
                        "'add_entrypoint_object' targets.")
  endif()

  get_fq_target_name(${target_name} fq_target_name)
  get_fq_deps_list(fq_deps_list ${DIFF_DEPENDS})
  get_object_files_for_test(
      link_object_files skipped_entrypoints_list ${fq_deps_list})
  if(skipped_entrypoints_list)
    set(msg "Will not build ${fq_target_name} as it has missing deps: "
            "${skipped_entrypoints_list}.")
    message(STATUS ${msg})
    return()
  endif()

  add_executable(
    ${fq_target_name}
    EXCLUDE_FROM_ALL
    ${DIFF_SRCS}
    ${DIFF_HDRS}
  )
  target_include_directories(
    ${fq_target_name}
    PRIVATE
      ${LIBC_SOURCE_DIR}
      ${LIBC_BUILD_DIR}
      ${LIBC_BUILD_DIR}/include
  )
  if(DIFF_COMPILE_OPTIONS)
    target_compile_options(
      ${fq_target_name}
      PRIVATE ${DIFF_COMPILE_OPTIONS}
    )
  endif()

  target_link_libraries(
      ${fq_target_name}
      PRIVATE ${link_object_files} libc_test_utils)

  set_target_properties(${fq_target_name}
    PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

  add_dependencies(
    ${fq_target_name}
    libc.utils.FPUtil.fputil
    ${fq_deps_list}
  )
endfunction()

add_header_library(
  single_input_single_output_diff
  HDRS
    SingleInputSingleOutputDiff.h
)

add_diff_binary(
  sinf_diff
  SRCS
    sinf_diff.cpp
  DEPENDS
    .single_input_single_output_diff
    libc.src.math.sinf
)

add_diff_binary(
  sinf_perf
  SRCS
    sinf_perf.cpp
  DEPENDS
    .single_input_single_output_diff
    libc.src.math.sinf
  COMPILE_OPTIONS
    -fno-builtin
)

add_diff_binary(
  cosf_diff
  SRCS
    cosf_diff.cpp
  DEPENDS
    .single_input_single_output_diff
    libc.src.math.cosf
)

add_diff_binary(
  cosf_perf
  SRCS
    cosf_perf.cpp
  DEPENDS
    .single_input_single_output_diff
    libc.src.math.cosf
  COMPILE_OPTIONS
    -fno-builtin
)

add_diff_binary(
  expm1f_diff
  SRCS
    expm1f_diff.cpp
  DEPENDS
    .single_input_single_output_diff
    libc.src.math.expm1f
)

add_diff_binary(
  expm1f_perf
  SRCS
    expm1f_perf.cpp
  DEPENDS
    .single_input_single_output_diff
    libc.src.math.expm1f
  COMPILE_OPTIONS
    -fno-builtin
)
