add_library(util
  audio_stream.cpp
  audio_stream.h
  cd_image.cpp
  cd_image.h
  cd_image_bin.cpp
  cd_image_cue.cpp
  cd_image_chd.cpp
  cd_image_device.cpp
  cd_image_ecm.cpp
  cd_image_hasher.cpp
  cd_image_hasher.h
  cd_image_m3u.cpp
  cd_image_memory.cpp
  cd_image_mds.cpp
  cd_image_pbp.cpp
  cd_image_ppf.cpp
  cd_subchannel_replacement.cpp
  cd_subchannel_replacement.h
  cd_xa.cpp
  cd_xa.h
  cue_parser.cpp
  cue_parser.h
  gpu_device.cpp
  gpu_device.h
  gpu_shader_cache.cpp
  gpu_shader_cache.h
  gpu_texture.cpp
  gpu_texture.h
  host.cpp
  host.h
  imgui_fullscreen.cpp
  imgui_fullscreen.h
  imgui_manager.cpp
  imgui_manager.h
  ini_settings_interface.cpp
  ini_settings_interface.h
  input_manager.cpp
  input_manager.h
  input_source.cpp
  input_source.h
  iso_reader.cpp
  iso_reader.h
  jit_code_buffer.cpp
  jit_code_buffer.h
  memory_arena.cpp
  memory_arena.h
  page_fault_handler.cpp
  page_fault_handler.h
  platform_misc.h
  postprocessing.cpp
  postprocessing.h
  postprocessing_shader.cpp
  postprocessing_shader.h
  postprocessing_shader_fx.cpp
  postprocessing_shader_fx.h
  postprocessing_shader_glsl.cpp
  postprocessing_shader_glsl.h
  shadergen.cpp
  shadergen.h
  shiftjis.cpp
  shiftjis.h
  state_wrapper.cpp
  state_wrapper.h
  wav_writer.cpp
  wav_writer.h
  window_info.cpp
  window_info.h
)

target_include_directories(util PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_link_libraries(util PUBLIC common simpleini imgui)
target_link_libraries(util PRIVATE stb libchdr zlib soundtouch Zstd::Zstd reshadefx)

if(ENABLE_CUBEB)
  target_sources(util PRIVATE
    cubeb_audio_stream.cpp
    cubeb_audio_stream.h
  )
  target_compile_definitions(util PUBLIC "WITH_CUBEB=1")
  target_link_libraries(util PRIVATE cubeb)
endif()

if(USE_X11)
  target_compile_definitions(util PRIVATE "-DUSE_X11=1")
  target_include_directories(util PRIVATE "${X11_INCLUDE_DIR}" "${X11_Xrandr_INCLUDE_PATH}")
  target_link_libraries(util PRIVATE "${X11_LIBRARIES}" "${X11_Xrandr_LIB}")
endif()

if(USE_WAYLAND)
  target_compile_definitions(util PRIVATE "-DUSE_WAYLAND=1")
elseif(SUPPORTS_WAYLAND)
  message(WARNING "Wayland support for renderers is disabled.\nDuckStation will FAIL to start on Wayland.")
endif()

if(ENABLE_OPENGL)
  target_sources(util PRIVATE
    gl/context.cpp
    gl/context.h
    opengl_device.cpp
    opengl_device.h
    opengl_loader.h
    opengl_pipeline.cpp
    opengl_pipeline.h
    opengl_stream_buffer.cpp
    opengl_stream_buffer.h
    opengl_texture.cpp
    opengl_texture.h
  )
  target_compile_definitions(util PUBLIC "WITH_OPENGL=1")
  target_link_libraries(util PRIVATE glad)

  if(WIN32)
    target_sources(util PRIVATE
      gl/context_wgl.cpp
      gl/context_wgl.h
    )
  endif()

  if(LINUX OR FREEBSD OR ANDROID)
    target_sources(util PRIVATE
      gl/context_egl.cpp
      gl/context_egl.h
    )
    target_compile_definitions(util PRIVATE "-DUSE_EGL=1")

    if(USE_X11)
      target_sources(util PRIVATE
        gl/context_egl_x11.cpp
        gl/context_egl_x11.h
      )

      # We set EGL_NO_X11 because otherwise X comes in with its macros and breaks
      # a bunch of files from compiling, if we include the EGL headers. This just
      # makes the data types opaque, we can still use it with X11 if needed.
      target_compile_definitions(util PRIVATE "-DEGL_NO_X11=1")
    endif()
    if(USE_WAYLAND)
      target_sources(util PRIVATE
        gl/context_egl_wayland.cpp
        gl/context_egl_wayland.h
      )
    endif()
    if(ANDROID)
      target_sources(util PRIVATE
        gl/context_egl_android.cpp
        gl/context_egl_android.h
      )
    endif()
  endif()

  if(APPLE)
    target_sources(util PRIVATE
      gl/context_agl.mm
      gl/context_agl.h
    )
  endif()
endif()

if(ENABLE_VULKAN OR APPLE)
  target_sources(util PRIVATE
    spirv_compiler.cpp
    spirv_compiler.h
  )
  target_link_libraries(util PRIVATE glslang)
  if(APPLE)
    target_link_libraries(util PRIVATE spirv-cross)
  endif()
endif()

if(ENABLE_VULKAN)
  target_sources(util PRIVATE
    vulkan_builders.cpp
    vulkan_builders.h
    vulkan_device.cpp
    vulkan_device.h
    vulkan_entry_points.h
    vulkan_entry_points.inl
    vulkan_loader.cpp
    vulkan_loader.h
    vulkan_pipeline.cpp
    vulkan_pipeline.h
    vulkan_stream_buffer.cpp
    vulkan_stream_buffer.h
    vulkan_swap_chain.cpp
    vulkan_swap_chain.h
    vulkan_texture.cpp
    vulkan_texture.h
  )
  target_compile_definitions(util PUBLIC "WITH_VULKAN=1")

  if(APPLE)
    # Needed for Vulkan Swap Chain.
    target_link_libraries(util PRIVATE "objc")
  endif()
endif()

if(SDL2_FOUND)
  target_sources(util PRIVATE 
    sdl_input_source.cpp
    sdl_input_source.h
  )
  target_compile_definitions(util PUBLIC "WITH_SDL2=1")
  target_include_directories(util PUBLIC ${SDL2_INCLUDE_DIRS})
  target_link_libraries(util PUBLIC ${SDL2_LIBRARIES})

  # Copy bundled SDL2 to output on Windows.
  if(WIN32)
    add_custom_command(TARGET util POST_BUILD
      COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_DLL_PATH}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/SDL2.dll")
  endif()
endif()

if(USE_DBUS)
	target_compile_definitions(util PRIVATE USE_DBUS)
	find_package(PkgConfig REQUIRED)
	pkg_check_modules(DBUS REQUIRED dbus-1)
	target_include_directories(util PRIVATE ${DBUS_INCLUDE_DIRS})
	target_link_libraries(util PRIVATE ${DBUS_LINK_LIBRARIES})
endif()

if(WIN32)
  target_sources(util PRIVATE
    dinput_source.cpp
    dinput_source.h
    platform_misc_win32.cpp
    win32_raw_input_source.cpp
    win32_raw_input_source.h
    xaudio2_audio_stream.cpp
    xaudio2_audio_stream.h
    xinput_source.cpp
    xinput_source.h
  )
  target_link_libraries(util PRIVATE d3d11.lib d3d12.lib d3dcompiler.lib dxgi.lib winmm.lib)
elseif(APPLE)
  target_sources(util PRIVATE
    cocoa_tools.h
    metal_device.h
    metal_device.mm
    metal_stream_buffer.h
    metal_stream_buffer.mm
    platform_misc_mac.mm
  )
  find_library(IOK_LIBRARY IOKit REQUIRED)
  find_library(METAL_LIBRARY Metal)
  find_library(QUARTZCORE_LIBRARY QuartzCore)
  target_link_libraries(util PRIVATE ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY} ${IOK_LIBRARY})
elseif(NOT ANDROID)
  target_sources(util PRIVATE
    platform_misc_unix.cpp
  )
endif()
