cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url

project(fastfetch
    VERSION 2.67.0
    LANGUAGES C
    DESCRIPTION "Fast neofetch-like system information tool"
    HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
)

set(PROJECT_LICENSE "MIT license")

if(DEFINED CMAKE_SYSTEM_PROCESSOR_OVERRIDE) # Used by github actions for i686 build
    set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR_OVERRIDE} CACHE INTERNAL "")
endif()
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" CMAKE_SYSTEM_PROCESSOR)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
    set(CMAKE_SYSTEM_PROCESSOR "amd64")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
    set(CMAKE_SYSTEM_PROCESSOR "aarch64")
endif()
message(STATUS "Build for system processor: ${CMAKE_SYSTEM_PROCESSOR}")

###################
# Target Platform #
###################
if(ANDROID)
    set(LINUX FALSE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
    set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
    set(FreeBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD")
    set(OpenBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "MidnightBSD")
    set(FreeBSD TRUE CACHE BOOL "..." FORCE)
    set(MidnightBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "NetBSD")
    set(NetBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")
    set(FreeBSD TRUE CACHE BOOL "..." FORCE)
    set(DragonFly TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
    set(SunOS TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Haiku")
    set(Haiku TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "GNU")
    set(GNU TRUE CACHE BOOL "..." FORCE)
elseif(NOT APPLE AND NOT WIN32)
    message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()

#############################
# Compile time dependencies #
#############################

set(THREADS_PREFER_PTHREAD_FLAG NOT WIN32)
find_package(Threads)

find_package(PkgConfig)
if(NOT PKG_CONFIG_FOUND)
    message(WARNING "pkg-config not found, library detection might be limited")
endif()

include(CheckIncludeFile)
include(CheckFunctionExists)

if(LINUX)
    CHECK_INCLUDE_FILE("linux/version.h" HAVE_LINUX_VERSION_H)
    if(NOT HAVE_LINUX_VERSION_H)
        message(FATAL_ERROR "Linux headers (linux/version.h) not found! Please install linux-headers package.")
    endif()
endif()

#####################
# Configure options #
#####################

include(CMakeDependentOption)

cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VADRM "Enable libva-drm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VAX11 "Enable libva-x11" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VDPAU "Enable vdpau" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_EET "Enable eet" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX OR GNU" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR ANDROID OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR ANDROID OR GNU" OFF)
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)

option(ENABLE_ZLIB "Enable zlib" ON)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_TRACER "Build fastfetch with function tracing" OFF)
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
option(BUILD_FLASHFETCH "Build flashfetch" ON) # Also build the flashfetch binary
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON)
option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF)
option(ENABLE_EMBEDDED_AMDGPUIDS "Embed amdgpu.ids into fastfetch, requires `python`" OFF)
option(ENABLE_WORDEXP "Enable using of wordexp(3) if available, instead of glob(3)" ON)
option(ENABLE_LUA "Enable lua scripting for format strings" ON)
option(ENABLE_QUICKJS "Enable quickjs scripting for format strings" ON)
option(ENABLE_LIBZFS "Enable libzfs" ON)
option(ENABLE_WCWIDTH "Detect wide-width characters with wcwidth when calculating logo and separator width. Disable for a smaller and slightly faster build, but logos containing CJK/emoji may be measured too narrow and render incorrectly. Such usecases are uncommon." ON)
set(DEFAULT_STRUCTURE "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:LocalIp:Battery:PowerAdapter:Locale:Break:Colors" CACHE STRING "Default module structure for detection")
if(WIN32 AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
    option(ENABLE_WIN81_COMPAT "Enable legacy Windows compatibility (Windows 8.1 and later; Windows 7 unsupported)" ON)
endif()
if(APPLE)
    option(ENABLE_APPLE_MEMSIZE_USABLE "Use usable memory size as total memory size in Memory module, to match other systems" OFF)
endif()

file(GLOB FF_MODULE_DIRS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/modules" "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/*/")
foreach(FF_MODULE_DIR ${FF_MODULE_DIRS})
    if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/${FF_MODULE_DIR}")
        string(TOUPPER "${FF_MODULE_DIR}" FF_MODULE_UPPER)
        option(MODULE_DISABLE_${FF_MODULE_UPPER} "Disable module ${FF_MODULE_DIR}" OFF)
    endif()
endforeach()

set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
set_property(CACHE BINARY_LINK_TYPE PROPERTY STRINGS ${BINARY_LINK_TYPE_OPTIONS})
if(NOT BINARY_LINK_TYPE IN_LIST BINARY_LINK_TYPE_OPTIONS)
    message(FATAL_ERROR "BINARY_LINK_TYPE must be one of ${BINARY_LINK_TYPE_OPTIONS}")
endif()

file(READ "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/packages/option.h" PACKAGE_MANAGERS)
string(REGEX MATCHALL "FF_PACKAGES_FLAG_[A-Z]+_BIT" PACKAGE_MANAGERS "${PACKAGE_MANAGERS}")
string(REGEX REPLACE "FF_PACKAGES_FLAG_([A-Z]+)_BIT" "\\1" PACKAGE_MANAGERS "${PACKAGE_MANAGERS}")
list(SORT PACKAGE_MANAGERS)
foreach(package_manager ${PACKAGE_MANAGERS})
    if(package_manager STREQUAL "WINGET")
        option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" ON)
    else()
        option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" OFF)
    endif()
endforeach()
option(PACKAGES_REMOVE_DISABLED "Remove disabled package managers from the build entirely, instead of just skipping them at runtime" OFF)

if (LINUX)
    set(CUSTOM_PCI_IDS_PATH "" CACHE STRING "Custom path to file pci.ids, defaults to `/usr/share/hwdata/pci.ids`")
    set(CUSTOM_AMDGPU_IDS_PATH "" CACHE STRING "Custom path to file amdgpu.ids, defaults to `/usr/share/libdrm/amdgpu.ids`")
    set(CUSTOM_OS_RELEASE_PATH "" CACHE STRING "Custom path to file os-release, defaults to `/etc/os-release`")
endif()

####################
# Compiler options #
####################

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
if(ENABLE_THREADS)
    if(CMAKE_USE_WIN32_THREADS_INIT)
        message(STATUS "Threads type: Win32 thread")
    elseif(CMAKE_USE_PTHREADS_INIT)
        message(STATUS "Threads type: pthread")
    endif()
else()
    message(STATUS "Threads type: disabled")
endif()

set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=return-type -Werror=vla")

if(LINUX)
    if(NOT IS_MUSL) # `NOT DEFINED IS_MUSL` doesn't work
        execute_process(
            COMMAND ${CMAKE_C_COMPILER} -print-file-name=libc.so
            OUTPUT_VARIABLE LIBC_PATH
            OUTPUT_STRIP_TRAILING_WHITESPACE
        )

        if(LIBC_PATH MATCHES "-musl")
            set(IS_MUSL ON CACHE BOOL "Build with musl libc" FORCE)
        endif()
    endif()

    if(IS_MUSL)
        message(STATUS "MUSL libc detected")
        # Silence ioctl related warnings
        set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-sign-conversion")
    endif()
endif()

# Minimal compiler version supported: GCC 13 (2023-04-26), Clang 16 (2023-03-17)
# Most C23 features are allowed with noticeable exceptions of `constexpr` and `#embed`
# See https://cppreference.com/c/compiler_support/23 for detail
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion")

if(WIN32 OR Haiku)
    enable_language(CXX)
    if(WIN32)
        set(CMAKE_CXX_STANDARD 20)
    else()
        set(CMAKE_CXX_STANDARD 17)
    endif()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}")
endif()

if(WIN32)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id")

    if(ENABLE_WIN81_COMPAT)
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--subsystem,console,--major-os-version,6,--minor-os-version,3")
    else()
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--subsystem,console,--major-os-version,10,--minor-os-version,0")
    endif()
elseif(APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc")
endif()

set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
if(ENABLE_ASAN)
    message(STATUS "Address sanitizer enabled (DEBUG only)")
    set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -fstack-protector-all -fno-delete-null-pointer-checks")
if(NOT WIN32)
    set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
endif()

if(ENABLE_LTO AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
    message(STATUS "Enabling LTO")
    include(CheckIPOSupported)
    check_ipo_supported(RESULT IPO_SUPPORTED)
    if(IPO_SUPPORTED)
        set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
    endif()
endif()

#######################
# Target FS structure #
#######################

if(NOT TARGET_DIR_ROOT)
    if(NOT ANDROID)
        set(TARGET_DIR_ROOT "")
    else()
        set(TARGET_DIR_ROOT "/data/data/com.termux/files/usr")
    endif()
endif()

if(NOT TARGET_DIR_USR)
    if(NOT ANDROID)
        set(TARGET_DIR_USR "${TARGET_DIR_ROOT}/usr")
    else()
        set(TARGET_DIR_USR "${TARGET_DIR_ROOT}")
    endif()
endif()

if(NOT TARGET_DIR_HOME)
    if(APPLE)
        set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/Users")
    elseif(ANDROID)
        set(TARGET_DIR_HOME "/data/data/com.termux/files/home")
    else()
        set(TARGET_DIR_HOME "${TARGET_DIR_ROOT}/home")
    endif()
endif()

if(NOT TARGET_DIR_ETC)
    set(TARGET_DIR_ETC "${TARGET_DIR_ROOT}/etc")
endif()

message(STATUS "Target dirs: ROOT=\"${TARGET_DIR_ROOT}\" USR=\"${TARGET_DIR_USR}\" HOME=\"${TARGET_DIR_HOME}\" ETC=\"${TARGET_DIR_ETC}\"")

#https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
    set(CMAKE_INSTALL_PREFIX "${TARGET_DIR_USR}" CACHE PATH "..." FORCE)
endif()

if(NOT CMAKE_INSTALL_SYSCONFDIR)
    set(CMAKE_INSTALL_SYSCONFDIR "${TARGET_DIR_ETC}" CACHE PATH "..." FORCE)
endif()

#################
# Tweak version #
#################

if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
    execute_process(
        COMMAND git describe --tags
        WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
        OUTPUT_VARIABLE PROJECT_VERSION_GIT
        OUTPUT_STRIP_TRAILING_WHITESPACE
    )
    string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_GIT}")
endif()
if(PROJECT_VERSION_TWEAK)
    string(REGEX MATCH "[0-9]+" PROJECT_VERSION_TWEAK_NUM "${PROJECT_VERSION_TWEAK}")
else()
    set(PROJECT_VERSION_TWEAK_NUM 0)
endif()

#############
# Text data #
#############

function(fastfetch_encode_c_string STR OUTVAR)
    string(REGEX REPLACE "\n$" "" TEMP "${STR}")  # Remove trailing newline
    string(REPLACE "\\" "\\\\" TEMP "${TEMP}")    # Escape backslashes
    string(REPLACE "\n" "\\n" TEMP "${TEMP}")     # Replace newlines with \n
    string(REPLACE "\"" "\\\"" TEMP "${TEMP}")    # Replace quotes with \"
    set(${OUTVAR} "\"${TEMP}\"" PARENT_SCOPE)
endfunction(fastfetch_encode_c_string)

function(fastfetch_load_text FILENAME OUTVAR)
    file(READ "${FILENAME}" TEMP)
    fastfetch_encode_c_string("${TEMP}" TEMP)
    set(${OUTVAR} "${TEMP}" PARENT_SCOPE)
endfunction(fastfetch_load_text)

find_package(Python)
if(Python_FOUND)
    message(STATUS "Minifying 'help.json'")
    execute_process(COMMAND ${Python_EXECUTABLE} -c "import json,sys;json.dump(json.load(sys.stdin),sys.stdout,separators=(',',':'))"
                    INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/doc/help.json"
                    OUTPUT_VARIABLE DATATEXT_JSON_HELP)
    if(DATATEXT_JSON_HELP STREQUAL "")
        message(ERROR "DATATEXT_JSON_HELP is empty, which should not happen!")
    endif()
else()
    message(WARNING "Python3 is not found, 'help.json' will not be minified")
    file(READ "${CMAKE_CURRENT_SOURCE_DIR}/doc/help.json" DATATEXT_JSON_HELP)
endif()

if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
    if(Python_FOUND)
        if(NOT EXISTS "${PROJECT_BINARY_DIR}/pci.ids")
            message(STATUS "'${PROJECT_BINARY_DIR}/pci.ids' is missing, downloading...")
            file(DOWNLOAD "https://pci-ids.ucw.cz/v2.2/pci.ids" "${PROJECT_BINARY_DIR}/pci.ids")
        endif()
        message(STATUS "Generating 'fastfetch_pciids.c.inc'")
        execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py" "${PROJECT_BINARY_DIR}/pci.ids"
                        OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc"
                        RESULT_VARIABLE PYTHON_PCIIDS_RETCODE)
        if(NOT PYTHON_PCIIDS_RETCODE EQUAL 0)
            file(REMOVE "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
            message(WARNING "Failed to generate 'fastfetch_pciids.c.inc'")
            set(ENABLE_EMBEDDED_PCIIDS OFF)
        endif()
    else()
        message(WARNING "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated")
        set(ENABLE_EMBEDDED_PCIIDS OFF)
    endif()
endif()

if(ENABLE_EMBEDDED_AMDGPUIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc")
    if(Python_FOUND)
        if(NOT EXISTS "${PROJECT_BINARY_DIR}/amdgpu.ids")
            message(STATUS "'${PROJECT_BINARY_DIR}/amdgpu.ids' is missing, downloading...")
            file(DOWNLOAD "https://gitlab.freedesktop.org/mesa/drm/-/raw/main/data/amdgpu.ids" "${PROJECT_BINARY_DIR}/amdgpu.ids")
        endif()
        message(STATUS "Generating 'fastfetch_amdgpuids.c.inc'")
        execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-amdgpuids.py" "${PROJECT_BINARY_DIR}/amdgpu.ids"
                        OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc"
                        RESULT_VARIABLE PYTHON_AMDGPUIDS_RETCODE)
        if(NOT PYTHON_AMDGPUIDS_RETCODE EQUAL 0)
            file(REMOVE "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc")
            message(WARNING "Failed to generate 'fastfetch_amdgpuids.c.inc'")
            set(ENABLE_EMBEDDED_AMDGPUIDS OFF)
        endif()
    else()
        message(WARNING "Python3 is not found, 'fastfetch_amdgpuids.c.inc' will not be generated")
        set(ENABLE_EMBEDDED_AMDGPUIDS OFF)
    endif()
endif()

if(Python_FOUND)
    message(STATUS "Generating 'fastfetch.1'")
    execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-man.py"
                    OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch.1"
                    RESULT_VARIABLE PYTHON_MANPAGE_RETCODE)
        if(NOT PYTHON_MANPAGE_RETCODE EQUAL 0)
            message(FATAL_ERROR "Failed to generate 'fastfetch.1'")
        endif()
else()
    message(WARNING "Python3 is not found, use basic 'fastfetch.1.in' instead")
    string(TIMESTAMP FASTFETCH_BUILD_DATE "%d %B %Y" UTC)
    configure_file(doc/fastfetch.1.in fastfetch.1 @ONLY)
endif()

fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP)

configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
if(APPLE)
    configure_file(src/common/apple/Info.plist.in Info.plist @ONLY)
endif()

####################
# Ascii image data #
####################

file(GLOB LOGO_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/logo/ascii/[a-z_]/*.txt")
set(LOGO_BUILTIN_H "#pragma once\n#pragma GCC diagnostic ignored \"-Wtrigraphs\"\n\n")
foreach(file ${LOGO_FILES})
    fastfetch_load_text("${file}" content)
    get_filename_component(file "${file}" NAME_WE)
    string(TOUPPER "${file}" file)
    set(LOGO_BUILTIN_H "${LOGO_BUILTIN_H}#define FASTFETCH_DATATEXT_LOGO_${file} ${content}\n")
endforeach()
file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")

#######################
# libfastfetch target #
#######################

set(LIBFASTFETCH_SRC
    src/common/impl/commandoption.c
    src/common/impl/duration.c
    src/common/impl/font.c
    src/common/impl/format.c
    src/common/impl/frequency.c
    src/common/impl/genconfig.c
    src/common/impl/init.c
    src/common/impl/jsonconfig.c
    src/common/impl/library.c
    src/common/impl/lua.c
    src/common/impl/netif.c
    src/common/impl/networking_common.c
    src/common/impl/option.c
    src/common/impl/parsing.c
    src/common/impl/percent.c
    src/common/impl/printing.c
    src/common/impl/properties.c
    src/common/impl/settings.c
    src/common/impl/size.c
    src/common/impl/temps.c
    src/common/impl/time.c
    src/common/impl/edidHelper.c
    src/common/impl/base64.c
    src/common/impl/FFlist.c
    src/common/impl/FFstrbuf.c
    src/common/impl/path.c
    src/common/impl/FFPlatform.c
    src/common/impl/smbios.c
    src/common/impl/strutil.c
    src/detection/bluetoothradio/bluetoothradio.c
    src/detection/bootmgr/bootmgr.c
    src/detection/chassis/chassis.c
    src/detection/codec/codec.c
    src/detection/codec/codec_vulkan.c
    src/detection/cpu/cpu.c
    src/detection/cpu/cpu_x86.c
    src/detection/cpuusage/cpuusage.c
    src/detection/command/command.c
    src/detection/disk/disk.c
    src/detection/diskio/diskio.c
    src/detection/displayserver/displayserver.c
    src/detection/editor/editor.c
    src/detection/font/font.c
    src/detection/gpu/gpu.c
    src/detection/host/host_mac.c
    src/detection/media/media.c
    src/detection/netio/netio.c
    src/detection/opencl/opencl.c
    src/detection/opengl/opengl_shared.c
    src/detection/os/os.c
    src/detection/packages/packages.c
    src/detection/physicalmemory/physicalmemory.c
    src/detection/publicip/publicip.c
    src/detection/terminaltheme/terminaltheme.c
    src/detection/terminalfont/terminalfont.c
    src/detection/terminalshell/terminalshell.c
    src/detection/version/version.c
    src/detection/vulkan/vulkan.c
    src/detection/weather/weather.c
    src/detection/zpool/zpool.c
    src/logo/builtin.c
    src/logo/image/im6.c
    src/logo/image/im7.c
    src/logo/image/image.c
    src/logo/logo.c
    src/modules/battery/battery.c
    src/modules/bios/bios.c
    src/modules/bluetooth/bluetooth.c
    src/modules/bluetoothradio/bluetoothradio.c
    src/modules/board/board.c
    src/modules/bootmgr/bootmgr.c
    src/modules/brightness/brightness.c
    src/modules/break/break.c
    src/modules/btrfs/btrfs.c
    src/modules/camera/camera.c
    src/modules/chassis/chassis.c
    src/modules/codec/codec.c
    src/modules/colors/colors.c
    src/modules/cpu/cpu.c
    src/modules/cpucache/cpucache.c
    src/modules/cpuusage/cpuusage.c
    src/modules/cursor/cursor.c
    src/modules/custom/custom.c
    src/modules/command/command.c
    src/modules/datetime/datetime.c
    src/modules/de/de.c
    src/modules/disk/disk.c
    src/modules/diskio/diskio.c
    src/modules/dns/dns.c
    src/modules/editor/editor.c
    src/modules/font/font.c
    src/modules/gpu/gpu.c
    src/modules/host/host.c
    src/modules/icons/icons.c
    src/modules/initsystem/initsystem.c
    src/modules/gamepad/gamepad.c
    src/modules/kernel/kernel.c
    src/modules/keyboard/keyboard.c
    src/modules/lm/lm.c
    src/modules/loadavg/loadavg.c
    src/modules/locale/locale.c
    src/modules/localip/localip.c
    src/modules/logo/logo.c
    src/modules/memory/memory.c
    src/modules/monitor/monitor.c
    src/modules/netio/netio.c
    src/modules/opencl/opencl.c
    src/modules/opengl/opengl.c
    src/modules/os/os.c
    src/modules/packages/packages.c
    src/modules/physicaldisk/physicaldisk.c
    src/modules/physicalmemory/physicalmemory.c
    src/modules/processes/processes.c
    src/modules/player/player.c
    src/modules/poweradapter/poweradapter.c
    src/modules/publicip/publicip.c
    src/modules/display/display.c
    src/modules/separator/separator.c
    src/modules/shell/shell.c
    src/modules/sound/sound.c
    src/modules/swap/swap.c
    src/modules/media/media.c
    src/modules/mouse/mouse.c
    src/modules/terminal/terminal.c
    src/modules/terminaltheme/terminaltheme.c
    src/modules/terminalfont/terminalfont.c
    src/modules/terminalsize/terminalsize.c
    src/modules/theme/theme.c
    src/modules/title/title.c
    src/modules/tpm/tpm.c
    src/modules/uptime/uptime.c
    src/modules/users/users.c
    src/modules/version/version.c
    src/modules/vulkan/vulkan.c
    src/modules/wallpaper/wallpaper.c
    src/modules/weather/weather.c
    src/modules/wifi/wifi.c
    src/modules/wm/wm.c
    src/modules/wmtheme/wmtheme.c
    src/modules/zpool/zpool.c
    src/modules/modules.c
    src/options/display.c
    src/options/logo.c
    src/options/general.c
)

if(LINUX)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_linux.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/kmod_linux.c
        src/detection/battery/battery_linux.c
        src/detection/bios/bios_linux.c
        src/detection/board/board_linux.c
        src/detection/bootmgr/bootmgr_linux.c
        src/detection/brightness/brightness_linux.c
        src/detection/btrfs/btrfs_linux.c
        src/detection/chassis/chassis_linux.c
        src/detection/codec/codec_linux.c
        src/detection/cpu/cpu_linux.c
        src/detection/cpucache/cpucache_linux.c
        src/detection/cpuusage/cpuusage_linux.c
        src/detection/cursor/cursor_linux.c
        src/detection/bluetooth/bluetooth_linux.c
        src/detection/bluetoothradio/bluetoothradio_linux.c
        src/detection/disk/disk_linux.c
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_linux.c
        src/detection/physicalmemory/physicalmemory_linux.c
        src/detection/diskio/diskio_linux.c
        src/detection/displayserver/linux/displayserver_linux.c
        src/detection/displayserver/linux/common.c
        src/detection/displayserver/linux/drm.c
        src/detection/displayserver/linux/wayland/wayland.c
        src/detection/displayserver/linux/wayland/global-output.c
        src/detection/displayserver/linux/wayland/wl-output-protocol.c
        src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
        src/detection/displayserver/linux/wayland/kde-output.c
        src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
        src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
        src/detection/displayserver/linux/wmde.c
        src/detection/displayserver/linux/xcb.c
        src/detection/displayserver/linux/xlib.c
        src/detection/font/font_linux.c
        src/detection/gpu/gpu_linux.c
        src/detection/gpu/gpu_drm.c
        src/detection/gpu/gpu_pci.c
        src/detection/gpu/gpu_windows.c
        src/detection/gtk_qt/gtk.c
        src/detection/host/host_linux.c
        src/detection/icons/icons_linux.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_linux.c
        src/detection/libc/libc_linux.c
        src/detection/lm/lm_linux.c
        src/detection/loadavg/loadavg_linux.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_linux.c
        src/detection/media/media_linux.c
        src/detection/memory/memory_linux.c
        src/detection/mouse/mouse_linux.c
        src/detection/netio/netio_linux.c
        src/detection/opengl/opengl_linux.c
        src/detection/os/os_linux.c
        src/detection/packages/packages_linux.c
        src/detection/packages/packages_nix.c
        src/detection/poweradapter/poweradapter_linux.c
        src/detection/processes/processes_linux.c
        src/detection/gtk_qt/qt.c
        src/detection/sound/sound_linux.c
        src/detection/swap/swap_linux.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_linux.c
        src/detection/tpm/tpm_linux.c
        src/detection/uptime/uptime_linux.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_linux.c
        src/detection/wifi/wifi_linux.c
        src/detection/wm/wm_linux.c
        src/detection/de/de_linux.c
        src/detection/wmtheme/wmtheme_linux.c
        src/detection/camera/camera_linux.c
    )
elseif(ANDROID)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_linux.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/kmod_linux.c
        src/detection/battery/battery_android.c
        src/detection/bios/bios_android.c
        src/detection/bluetooth/bluetooth_nosupport.c
        src/detection/bluetoothradio/bluetoothradio_nosupport.c
        src/detection/board/board_android.c
        src/detection/bootmgr/bootmgr_nosupport.c
        src/detection/brightness/brightness_nosupport.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_nosupport.c
        src/detection/codec/codec_android.c
        src/detection/cpu/cpu_linux.c
        src/detection/cpucache/cpucache_linux.c
        src/detection/cursor/cursor_linux.c
        src/detection/cpuusage/cpuusage_linux.c
        src/detection/disk/disk_linux.c
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_linux.c
        src/detection/physicalmemory/physicalmemory_nosupport.c
        src/detection/diskio/diskio_linux.c
        src/detection/displayserver/displayserver_android.c
        src/detection/displayserver/linux/common.c
        src/detection/displayserver/linux/wmde.c
        src/detection/displayserver/linux/xcb.c
        src/detection/displayserver/linux/xlib.c
        src/detection/gtk_qt/gtk.c
        src/detection/gtk_qt/qt.c
        src/detection/font/font_linux.c
        src/detection/gpu/gpu_android.c
        src/detection/host/host_android.c
        src/detection/icons/icons_linux.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_nosupport.c
        src/detection/libc/libc_android.c
        src/detection/lm/lm_nosupport.c
        src/detection/loadavg/loadavg_linux.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_nosupport.c
        src/detection/media/media_linux.c
        src/detection/memory/memory_linux.c
        src/detection/mouse/mouse_nosupport.c
        src/detection/netio/netio_linux.c
        src/detection/opengl/opengl_linux.c
        src/detection/os/os_android.c
        src/detection/packages/packages_linux.c
        src/detection/packages/packages_nix.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_linux.c
        src/detection/sound/sound_linux.c
        src/detection/swap/swap_linux.c
        src/detection/terminalfont/terminalfont_android.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_linux.c
        src/detection/tpm/tpm_nosupport.c
        src/detection/uptime/uptime_linux.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_linux.c
        src/detection/wifi/wifi_android.c
        src/detection/wm/wm_linux.c
        src/detection/de/de_linux.c
        src/detection/wmtheme/wmtheme_linux.c
        src/detection/camera/camera_android.c
    )
elseif(FreeBSD)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_bsd.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/sysctl.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/kmod_bsd.c
        src/detection/battery/battery_bsd.c
        src/detection/bios/bios_bsd.c
        src/detection/bluetoothradio/bluetoothradio_nosupport.c
        src/detection/board/board_bsd.c
        src/detection/bootmgr/bootmgr_bsd.c
        src/detection/brightness/brightness_bsd.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_bsd.c
        src/detection/codec/codec_linux.c
        src/detection/cpu/cpu_bsd.c
        src/detection/cpucache/cpucache_shared.c
        src/detection/cpuusage/cpuusage_bsd.c
        src/detection/cursor/cursor_linux.c
        src/detection/disk/disk_bsd.c
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_bsd.c
        src/detection/physicalmemory/physicalmemory_linux.c
        src/detection/diskio/diskio_bsd.c
        src/detection/displayserver/linux/displayserver_linux.c
        src/detection/displayserver/linux/common.c
        src/detection/displayserver/linux/drm.c
        src/detection/displayserver/linux/wayland/wayland.c
        src/detection/displayserver/linux/wayland/global-output.c
        src/detection/displayserver/linux/wayland/kde-output.c
        src/detection/displayserver/linux/wayland/wl-output-protocol.c
        src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
        src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
        src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
        src/detection/displayserver/linux/wmde.c
        src/detection/displayserver/linux/xcb.c
        src/detection/displayserver/linux/xlib.c
        src/detection/font/font_linux.c
        src/detection/gpu/gpu_bsd.c
        src/detection/gpu/gpu_drm.c
        src/detection/gpu/gpu_pci.c
        src/detection/gpu/gpu_bsddrm.c
        src/detection/gtk_qt/gtk.c
        src/detection/host/host_bsd.c
        src/detection/lm/lm_linux.c
        src/detection/icons/icons_linux.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_bsd.c
        src/detection/libc/libc_bsd.c
        src/detection/loadavg/loadavg_bsd.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_bsd.c
        src/detection/media/media_linux.c
        src/detection/memory/memory_bsd.c
        src/detection/mouse/mouse_bsd.c
        src/detection/netio/netio_bsd.c
        src/detection/opengl/opengl_linux.c
        src/detection/os/os_linux.c
        src/detection/packages/packages_bsd.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_bsd.c
        src/detection/gtk_qt/qt.c
        src/detection/sound/sound_bsd.c
        src/detection/swap/swap_bsd.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_linux.c
        src/detection/tpm/tpm_bsd.c
        src/detection/uptime/uptime_bsd.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_linux.c
        src/detection/wm/wm_linux.c
        src/detection/de/de_linux.c
        src/detection/wmtheme/wmtheme_linux.c
        src/detection/camera/camera_linux.c
    )
    if(DragonFly)
        list(APPEND LIBFASTFETCH_SRC
            src/detection/bluetooth/bluetooth_nosupport.c
            src/detection/wifi/wifi_nosupport.c
        )
    else()
        list(APPEND LIBFASTFETCH_SRC
            src/detection/bluetooth/bluetooth_bsd.c
            src/detection/wifi/wifi_bsd.c
        )
    endif()
elseif(NetBSD)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_bsd.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/sysctl.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/kmod_nbsd.c
        src/detection/battery/battery_nbsd.c
        src/detection/bios/bios_nbsd.c
        src/detection/bluetooth/bluetooth_bsd.c
        src/detection/bluetoothradio/bluetoothradio_nosupport.c
        src/detection/board/board_nbsd.c
        src/detection/bootmgr/bootmgr_bsd.c
        src/detection/brightness/brightness_nbsd.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_nbsd.c
        src/detection/codec/codec_linux.c
        src/detection/cpu/cpu_nbsd.c
        src/detection/cpucache/cpucache_shared.c
        src/detection/cpuusage/cpuusage_bsd.c
        src/detection/cursor/cursor_linux.c
        src/detection/disk/disk_bsd.c
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_nbsd.c
        src/detection/physicalmemory/physicalmemory_linux.c
        src/detection/diskio/diskio_nbsd.c
        src/detection/displayserver/linux/displayserver_linux.c
        src/detection/displayserver/linux/common.c
        src/detection/displayserver/linux/drm.c
        src/detection/displayserver/linux/wayland/wayland.c
        src/detection/displayserver/linux/wayland/global-output.c
        src/detection/displayserver/linux/wayland/kde-output.c
        src/detection/displayserver/linux/wayland/wl-output-protocol.c
        src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
        src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
        src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
        src/detection/displayserver/linux/wmde.c
        src/detection/displayserver/linux/xcb.c
        src/detection/displayserver/linux/xlib.c
        src/detection/font/font_linux.c
        src/detection/gpu/gpu_nbsd.c
        src/detection/gpu/gpu_pci.c
        src/detection/gtk_qt/gtk.c
        src/detection/host/host_nbsd.c
        src/detection/lm/lm_linux.c
        src/detection/icons/icons_linux.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_nosupport.c
        src/detection/libc/libc_nosupport.c
        src/detection/loadavg/loadavg_bsd.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_nosupport.c
        src/detection/media/media_linux.c
        src/detection/memory/memory_nbsd.c
        src/detection/mouse/mouse_nosupport.c
        src/detection/netio/netio_bsd.c
        src/detection/opengl/opengl_linux.c
        src/detection/os/os_nbsd.c
        src/detection/packages/packages_nbsd.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_nbsd.c
        src/detection/gtk_qt/qt.c
        src/detection/sound/sound_nbsd.c
        src/detection/swap/swap_obsd.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_linux.c
        src/detection/tpm/tpm_nosupport.c
        src/detection/uptime/uptime_bsd.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_linux.c
        src/detection/wifi/wifi_nbsd.c
        src/detection/wm/wm_linux.c
        src/detection/de/de_linux.c
        src/detection/wmtheme/wmtheme_linux.c
        src/detection/camera/camera_linux.c
    )
elseif(OpenBSD)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_bsd.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/sysctl.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/smbios.c
        src/common/impl/kmod_nosupport.c
        src/detection/battery/battery_obsd.c
        src/detection/bios/bios_windows.c
        src/detection/bluetooth/bluetooth_nosupport.c
        src/detection/bluetoothradio/bluetoothradio_nosupport.c
        src/detection/board/board_windows.c
        src/detection/bootmgr/bootmgr_bsd.c
        src/detection/brightness/brightness_obsd.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_windows.c
        src/detection/codec/codec_linux.c
        src/detection/cpu/cpu_obsd.c
        src/detection/cpucache/cpucache_shared.c
        src/detection/cpuusage/cpuusage_bsd.c
        src/detection/cursor/cursor_linux.c
        src/detection/disk/disk_bsd.c
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_obsd.c
        src/detection/physicalmemory/physicalmemory_linux.c
        src/detection/diskio/diskio_obsd.c
        src/detection/displayserver/linux/displayserver_linux.c
        src/detection/displayserver/linux/common.c
        src/detection/displayserver/linux/drm.c
        src/detection/displayserver/linux/wayland/wayland.c
        src/detection/displayserver/linux/wayland/global-output.c
        src/detection/displayserver/linux/wayland/kde-output.c
        src/detection/displayserver/linux/wayland/wl-output-protocol.c
        src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
        src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
        src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
        src/detection/displayserver/linux/wmde.c
        src/detection/displayserver/linux/xcb.c
        src/detection/displayserver/linux/xlib.c
        src/detection/font/font_linux.c
        src/detection/gpu/gpu_pci.c
        src/detection/gpu/gpu_obsd.c
        src/detection/gpu/gpu_drm.c
        src/detection/gpu/gpu_bsddrm.c
        src/detection/gtk_qt/gtk.c
        src/detection/host/host_obsd.c
        src/detection/lm/lm_nosupport.c
        src/detection/icons/icons_linux.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_nosupport.c
        src/detection/libc/libc_nosupport.c
        src/detection/loadavg/loadavg_bsd.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_nosupport.c
        src/detection/media/media_linux.c
        src/detection/memory/memory_obsd.c
        src/detection/mouse/mouse_nosupport.c
        src/detection/netio/netio_bsd.c
        src/detection/opengl/opengl_linux.c
        src/detection/os/os_obsd.c
        src/detection/packages/packages_obsd.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_obsd.c
        src/detection/gtk_qt/qt.c
        src/detection/sound/sound_obsd.c
        src/detection/swap/swap_obsd.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_linux.c
        src/detection/tpm/tpm_nosupport.c
        src/detection/uptime/uptime_bsd.c
        src/detection/users/users_obsd.c
        src/detection/wallpaper/wallpaper_linux.c
        src/detection/wifi/wifi_obsd.c
        src/detection/wm/wm_linux.c
        src/detection/de/de_linux.c
        src/detection/wmtheme/wmtheme_linux.c
        src/detection/camera/camera_linux.c
    )
elseif(APPLE)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/io_unix.c
        src/common/impl/netif_apple.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/sysctl.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_apple.c
        src/common/impl/kmod_apple.c
        src/common/apple/cf_helpers.c
        src/common/apple/osascript.m
        src/common/apple/smc_temps.c
        src/common/apple/version.m
        src/detection/battery/battery_apple.c
        src/detection/bluetooth/bluetooth_apple.m
        src/detection/bluetoothradio/bluetoothradio_apple.m
        src/detection/bootmgr/bootmgr_apple.c
        src/detection/brightness/brightness_apple.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/codec/codec_apple.c
        src/detection/cpu/cpu_apple.c
        src/detection/cpucache/cpucache_apple.c
        src/detection/cpuusage/cpuusage_apple.c
        src/detection/cursor/cursor_apple.c
        src/detection/disk/disk_bsd.c
        src/detection/dns/dns_apple.c
        src/detection/physicaldisk/physicaldisk_apple.c
        src/detection/diskio/diskio_apple.c
        src/detection/displayserver/displayserver_apple.c
        src/detection/font/font_apple.m
        src/detection/gpu/gpu_apple.c
        src/detection/gpu/gpu_apple.m
        src/detection/icons/icons_nosupport.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_apple.c
        src/detection/lm/lm_nosupport.c
        src/detection/loadavg/loadavg_bsd.c
        src/detection/libc/libc_apple.c
        src/detection/locale/locale_apple.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_apple.c
        src/detection/media/media_apple.m
        src/detection/memory/memory_apple.c
        src/detection/mouse/mouse_apple.c
        src/detection/netio/netio_apple.c
        src/detection/opengl/opengl_apple.c
        src/detection/os/os_apple.m
        src/detection/packages/packages_apple.c
        src/detection/packages/packages_nix.c
        src/detection/poweradapter/poweradapter_apple.c
        src/detection/processes/processes_bsd.c
        src/detection/sound/sound_apple.c
        src/detection/swap/swap_apple.c
        src/detection/terminalfont/terminalfont_apple.m
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_apple.c
        src/detection/tpm/tpm_apple.c
        src/detection/uptime/uptime_bsd.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_apple.m
        src/detection/wifi/wifi_apple.m
        src/detection/wm/wm_apple.m
        src/detection/de/de_nosupport.c
        src/detection/wmtheme/wmtheme_apple.c
        src/detection/camera/camera_apple.m
    )
    # CMAKE_SYSTEM_PROCESSOR has been normalized before
    if(CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
        list(APPEND LIBFASTFETCH_SRC
            src/detection/bios/bios_windows.c
            src/detection/board/board_windows.c
            src/detection/chassis/chassis_windows.c
            src/detection/host/host_windows.c
            src/detection/physicalmemory/physicalmemory_linux.c
        )
    else()
        list(APPEND LIBFASTFETCH_SRC
            src/detection/bios/bios_apple.c
            src/detection/board/board_apple.c
            src/detection/chassis/chassis_apple.c
            src/detection/host/host_apple.c
            src/detection/physicalmemory/physicalmemory_apple.m
        )
    endif()
elseif(WIN32)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/io_windows.c
        src/common/impl/netif_windows.c
        src/common/impl/networking_windows.c
        src/common/impl/processing_windows.c
        src/common/impl/FFPlatform_windows.c
        src/common/impl/binary_windows.c
        src/common/impl/debug_windows.c
        src/common/impl/kmod_windows.c
        src/common/windows/getline.c
        src/common/windows/com.c
        src/common/windows/registry.c
        src/common/windows/unicode.c
        src/common/windows/variant.cpp
        src/common/windows/version.c
        src/detection/battery/battery_windows.c
        src/detection/bios/bios_windows.c
        src/detection/bluetooth/bluetooth_windows.c
        src/detection/bluetoothradio/bluetoothradio_windows.c
        src/detection/board/board_windows.c
        src/detection/bootmgr/bootmgr_windows.c
        src/detection/brightness/brightness_windows.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_windows.c
        src/detection/codec/codec_windows.cpp
        src/detection/cpu/cpu_windows.c
        src/detection/cpucache/cpucache_windows.c
        src/detection/cpuusage/cpuusage_windows.c
        src/detection/cursor/cursor_windows.c
        src/detection/disk/disk_windows.c
        src/detection/physicaldisk/physicaldisk_windows.c
        src/detection/diskio/diskio_windows.c
        src/detection/displayserver/displayserver_windows.c
        src/detection/dns/dns_windows.c
        src/detection/font/font_windows.c
        src/detection/gpu/gpu_windows.c
        src/detection/gpu/gpu_windows.cpp
        src/detection/host/host_windows.c
        src/detection/icons/icons_windows.c
        src/detection/initsystem/initsystem_windows.c
        src/detection/keyboard/keyboard_windows.c
        src/detection/libc/libc_windows.cpp
        src/detection/lm/lm_nosupport.c
        src/detection/loadavg/loadavg_nosupport.c
        src/detection/locale/locale_windows.c
        src/detection/localip/localip_windows.c
        src/detection/gamepad/gamepad_windows.c
        src/detection/media/media_windows.cpp
        src/detection/memory/memory_windows.c
        src/detection/mouse/mouse_windows.c
        src/detection/physicalmemory/physicalmemory_linux.c
        src/detection/netio/netio_windows.c
        src/detection/opengl/opengl_windows.c
        src/detection/os/os_windows.c
        src/detection/packages/packages_windows.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_windows.c
        src/detection/sound/sound_windows.cpp
        src/detection/swap/swap_windows.c
        src/detection/terminalfont/terminalfont_windows.c
        src/detection/terminalshell/terminalshell_windows.c
        src/detection/terminalsize/terminalsize_windows.c
        src/detection/theme/theme_windows.c
        src/detection/tpm/tpm_windows.c
        src/detection/uptime/uptime_windows.c
        src/detection/users/users_windows.c
        src/detection/wallpaper/wallpaper_windows.c
        src/detection/wifi/wifi_windows.c
        src/detection/wm/wm_windows.c
        src/detection/de/de_nosupport.c
        src/detection/wmtheme/wmtheme_windows.c
        src/detection/camera/camera_windows.cpp
    )
elseif(SunOS)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_apple.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/kmod_sunos.c
        src/detection/battery/battery_nosupport.c
        src/detection/bios/bios_windows.c
        src/detection/board/board_windows.c
        src/detection/bootmgr/bootmgr_nosupport.c
        src/detection/brightness/brightness_nosupport.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_windows.c
        src/detection/cpu/cpu_sunos.c
        src/detection/cpucache/cpucache_shared.c
        src/detection/cpuusage/cpuusage_sunos.c
        src/detection/cursor/cursor_linux.c
        src/detection/bluetooth/bluetooth_nosupport.c
        src/detection/bluetoothradio/bluetoothradio_nosupport.c
        src/detection/codec/codec_linux.c
        src/detection/disk/disk_sunos.c
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_sunos.c
        src/detection/physicalmemory/physicalmemory_linux.c
        src/detection/diskio/diskio_sunos.c
        src/detection/displayserver/linux/displayserver_linux.c
        src/detection/displayserver/linux/common.c
        src/detection/displayserver/linux/drm.c
        src/detection/displayserver/linux/wayland/wayland.c
        src/detection/displayserver/linux/wayland/global-output.c
        src/detection/displayserver/linux/wayland/kde-output.c
        src/detection/displayserver/linux/wayland/wl-output-protocol.c
        src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c
        src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
        src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
        src/detection/displayserver/linux/wmde.c
        src/detection/displayserver/linux/xcb.c
        src/detection/displayserver/linux/xlib.c
        src/detection/font/font_linux.c
        src/detection/gpu/gpu_sunos.c
        src/detection/gpu/gpu_pci.c
        src/detection/gtk_qt/gtk.c
        src/detection/host/host_windows.c
        src/detection/icons/icons_linux.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_nosupport.c
        src/detection/libc/libc_nosupport.c
        src/detection/lm/lm_nosupport.c
        src/detection/loadavg/loadavg_sunos.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_nosupport.c
        src/detection/media/media_linux.c
        src/detection/memory/memory_sunos.c
        src/detection/mouse/mouse_nosupport.c
        src/detection/netio/netio_sunos.c
        src/detection/opengl/opengl_linux.c
        src/detection/os/os_sunos.c
        src/detection/packages/packages_sunos.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_linux.c
        src/detection/gtk_qt/qt.c
        src/detection/sound/sound_sunos.c
        src/detection/swap/swap_sunos.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_linux.c
        src/detection/tpm/tpm_nosupport.c
        src/detection/uptime/uptime_sunos.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_linux.c
        src/detection/wifi/wifi_nosupport.c
        src/detection/wm/wm_nosupport.c
        src/detection/de/de_linux.c
        src/detection/wmtheme/wmtheme_linux.c
        src/detection/camera/camera_nosupport.c
    )
elseif(Haiku)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_haiku.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/kmod_nosupport.c
        src/common/haiku/version.cpp
        src/detection/battery/battery_haiku.c
        src/detection/bios/bios_windows.c
        src/detection/board/board_windows.c
        src/detection/bootmgr/bootmgr_haiku.cpp
        src/detection/brightness/brightness_haiku.cpp
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_windows.c
        src/detection/cpu/cpu_haiku.c
        src/detection/cpucache/cpucache_shared.c
        src/detection/cpuusage/cpuusage_haiku.c
        src/detection/cursor/cursor_nosupport.c
        src/detection/bluetooth/bluetooth_haiku.cpp
        src/detection/bluetoothradio/bluetoothradio_nosupport.c
        src/detection/codec/codec_linux.c
        src/detection/disk/disk_haiku.cpp
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_haiku.c
        src/detection/physicalmemory/physicalmemory_linux.c
        src/detection/diskio/diskio_nosupport.c
        src/detection/displayserver/displayserver_haiku.cpp
        src/detection/font/font_haiku.cpp
        src/detection/gpu/gpu_haiku.c
        src/detection/gpu/gpu_pci.c
        src/detection/gtk_qt/gtk.c
        src/detection/host/host_windows.c
        src/detection/icons/icons_nosupport.c
        src/detection/initsystem/initsystem_haiku.c
        src/detection/keyboard/keyboard_haiku.cpp
        src/detection/libc/libc_nosupport.c
        src/detection/lm/lm_nosupport.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_haiku.cpp
        src/detection/media/media_linux.c
        src/detection/memory/memory_haiku.c
        src/detection/mouse/mouse_haiku.cpp
        src/detection/netio/netio_haiku.cpp
        src/detection/opengl/opengl_haiku.cpp
        src/detection/os/os_haiku.c
        src/detection/packages/packages_haiku.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_haiku.c
        src/detection/gtk_qt/qt.c
        src/detection/sound/sound_haiku.cpp
        src/detection/swap/swap_haiku.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_nosupport.c
        src/detection/tpm/tpm_nosupport.c
        src/detection/uptime/uptime_haiku.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_haiku.cpp
        src/detection/wifi/wifi_nosupport.c
        src/detection/wm/wm_nosupport.c
        src/detection/de/de_nosupport.c
        src/detection/wmtheme/wmtheme_haiku.cpp
        src/detection/camera/camera_nosupport.c
    )
    set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} bsd)
    check_function_exists(getloadavg HAVE_GETLOADAVG)
    if(HAVE_GETLOADAVG)
        list(APPEND LIBFASTFETCH_SRC src/detection/loadavg/loadavg_sunos.c)
    else()
        list(APPEND LIBFASTFETCH_SRC src/detection/loadavg/loadavg_nosupport.c)
    endif()
elseif(GNU)
    list(APPEND LIBFASTFETCH_SRC
        src/common/impl/dbus.c
        src/common/impl/io_unix.c
        src/common/impl/netif_gnu.c
        src/common/impl/networking_linux.c
        src/common/impl/processing_linux.c
        src/common/impl/FFPlatform_unix.c
        src/common/impl/binary_linux.c
        src/common/impl/kmod_nosupport.c
        src/detection/battery/battery_nosupport.c
        src/detection/bios/bios_nosupport.c
        src/detection/board/board_nosupport.c
        src/detection/bootmgr/bootmgr_nosupport.c
        src/detection/brightness/brightness_nosupport.c
        src/detection/btrfs/btrfs_nosupport.c
        src/detection/chassis/chassis_nosupport.c
        src/detection/cpu/cpu_linux.c
        src/detection/cpucache/cpucache_nosupport.c
        src/detection/cpuusage/cpuusage_linux.c
        src/detection/cursor/cursor_linux.c
        src/detection/bluetooth/bluetooth_linux.c
        src/detection/bluetoothradio/bluetoothradio_linux.c
        src/detection/codec/codec_linux.c
        src/detection/disk/disk_linux.c
        src/detection/dns/dns_linux.c
        src/detection/physicaldisk/physicaldisk_nosupport.c
        src/detection/physicalmemory/physicalmemory_nosupport.c
        src/detection/diskio/diskio_nosupport.c
        src/detection/displayserver/linux/displayserver_linux.c
        src/detection/displayserver/linux/wayland/wayland.c
        src/detection/displayserver/linux/common.c
        src/detection/displayserver/linux/drm.c
        src/detection/displayserver/linux/wmde.c
        src/detection/displayserver/linux/xcb.c
        src/detection/displayserver/linux/xlib.c
        src/detection/font/font_linux.c
        src/detection/gpu/gpu_gnu.c
        src/detection/gpu/gpu_pci.c
        src/detection/gtk_qt/gtk.c
        src/detection/host/host_nosupport.c
        src/detection/icons/icons_linux.c
        src/detection/initsystem/initsystem_linux.c
        src/detection/keyboard/keyboard_nosupport.c
        src/detection/libc/libc_linux.c
        src/detection/lm/lm_linux.c
        src/detection/loadavg/loadavg_linux.c
        src/detection/locale/locale_linux.c
        src/detection/localip/localip_linux.c
        src/detection/gamepad/gamepad_nosupport.c
        src/detection/media/media_linux.c
        src/detection/memory/memory_linux.c
        src/detection/mouse/mouse_nosupport.c
        src/detection/netio/netio_nosupport.c
        src/detection/opengl/opengl_linux.c
        src/detection/os/os_linux.c
        src/detection/packages/packages_linux.c
        src/detection/packages/packages_nix.c
        src/detection/poweradapter/poweradapter_nosupport.c
        src/detection/processes/processes_linux.c
        src/detection/gtk_qt/qt.c
        src/detection/sound/sound_linux.c
        src/detection/swap/swap_linux.c
        src/detection/terminalfont/terminalfont_linux.c
        src/detection/terminalshell/terminalshell_linux.c
        src/detection/terminalsize/terminalsize_linux.c
        src/detection/theme/theme_linux.c
        src/detection/tpm/tpm_nosupport.c
        src/detection/uptime/uptime_linux.c
        src/detection/users/users_linux.c
        src/detection/wallpaper/wallpaper_linux.c
        src/detection/wifi/wifi_nosupport.c
        src/detection/wm/wm_linux.c
        src/detection/de/de_linux.c
        src/detection/wmtheme/wmtheme_linux.c
        src/detection/camera/camera_nosupport.c
   )
endif()

if(ENABLE_TRACER)
    message(STATUS "Tracer is enabled")
    list(APPEND LIBFASTFETCH_SRC src/common/impl/tracer.c)
    if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions-after-inlining")
    else()
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions -Dinline=\"__attribute__((no_instrument_function)) inline\"")
    endif()
    if(NOT WIN32)
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic")
    elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gcodeview -fuse-ld=lld")
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--pdb=${CMAKE_BINARY_DIR}/fastfetch.pdb")
    endif()
endif()

# Proprietary GPU driver APIs
if(LINUX OR FreeBSD OR WIN32)
    list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c)
    list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_mthreads.c)
endif()
if(WIN32)
    list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c)
    list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c)

    if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
        message(STATUS "WinRT support is disabled due to known issues with g++")
        set(HAVE_WINRT FALSE)
    else()
        include(CheckIncludeFileCXX)
        CHECK_INCLUDE_FILE_CXX("winrt/Windows.Foundation.h" HAVE_WINRT)
        if(HAVE_WINRT)
            message(STATUS "WinRT headers are available, media detection will be enabled")
        else()
            message(WARNING "WinRT headers are NOT available, media detection will be disabled")
        endif()
    endif()
endif()
if(NOT WIN32)
    check_function_exists(pipe2 HAVE_PIPE2)
endif()
check_function_exists(memrchr HAVE_MEMRCHR)
if(NOT HAVE_MEMRCHR)
    list(APPEND LIBFASTFETCH_SRC src/common/impl/memrchr.c)
endif()
if(ENABLE_WCWIDTH)
    list(APPEND LIBFASTFETCH_SRC src/common/impl/wcwidth.c)
endif()

if(ENABLE_SYSTEM_YYJSON)
    find_package(yyjson)
    if(yyjson_FOUND)
        message(STATUS "System provided yyjson is used")
    else()
        message(FATAL_ERROR "ENABLE_SYSTEM_YYJSON is set but system provided yyjson is not found")
    endif()
else()
    list(APPEND LIBFASTFETCH_SRC
        src/3rdparty/yyjson/yyjson.c
    )
endif()

add_library(libfastfetch OBJECT
    ${LIBFASTFETCH_SRC}
)

foreach(FF_MODULE_DIR ${FF_MODULE_DIRS})
    if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/${FF_MODULE_DIR}")
        string(TOUPPER "${FF_MODULE_DIR}" FF_MODULE_UPPER)
        if(MODULE_DISABLE_${FF_MODULE_UPPER})
            target_compile_definitions(libfastfetch PUBLIC FF_MODULE_DISABLE_${FF_MODULE_UPPER}=1)
        endif()
    endif()
endforeach()

include(CheckCSourceCompiles)
check_c_source_compiles("int main(void){int arr[1];return _Countof(arr);}" COMPILER_SUPPORTS_COUNT_OF)
if(COMPILER_SUPPORTS_COUNT_OF)
    message(STATUS "C2Y _Countof is supported by the compiler")
    target_compile_definitions(libfastfetch PUBLIC FF_SUPPORTS_COUNT_OF=1)
else()
    message(STATUS "C2Y _Countof is NOT supported by the compiler")
endif()

# Test C23 compiler support
check_c_source_compiles("enum my_enum: long{MY_ENUM_ZERO}; void test(void*p){} int main(int,const char**){[[gnu::cleanup(test)]] void* x=nullptr; return (int)MY_ENUM_ZERO;}" COMPILER_SUPPORTS_C23)
if(NOT COMPILER_SUPPORTS_C23)
    message(FATAL_ERROR "Compiler does not support C23. Please use a newer compiler.")
endif()

# A hack for AppleClang 17, which supports most C23 features we use except for the `auto` keyword.
# See https://github.com/Homebrew/homebrew-core/pull/297403
check_c_source_compiles("int main(void){auto v = 12.34; return (int)v;}" COMPILER_SUPPORTS_AUTO)
if(NOT COMPILER_SUPPORTS_AUTO)
    message(WARNING "Compiler does not support C23 'auto' keyword. A workaround will be applied.")
    target_compile_definitions(libfastfetch PUBLIC $<$<COMPILE_LANGUAGE:C>:auto=__auto_type>)
endif()

if(yyjson_FOUND)
    target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON=1)
    target_link_libraries(libfastfetch PUBLIC yyjson::yyjson)
    # `target_link_libraries(yyjson::yyjson)` sets rpath implicitly
endif()

# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE AND BINARY_LINK_TYPE STREQUAL "dlopen")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
endif()

if(ANDROID)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib64 -Wl,-rpath,/system/lib64")
    else()
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib -Wl,-rpath,/system/lib")
    endif()
endif()

if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
    execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1"
                    ERROR_VARIABLE LD_MUSL_RESULT)
    if("${LD_MUSL_RESULT}" MATCHES "Version ([0-9]+\\.[0-9]+\\.[0-9]+)")
        target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${CMAKE_MATCH_1}")
    endif()
endif()
if(APPLE AND EXISTS "/usr/bin/otool")
    execute_process(COMMAND /usr/bin/otool -L /usr/bin/otool
                    OUTPUT_VARIABLE OTOOL_OTOOL_RESULT)
    if("${OTOOL_OTOOL_RESULT}" MATCHES "libSystem\\.B\\.dylib \\(.*current version ([0-9]+\\.[0-9]+\\.[0-9]+)\\)")
        target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}")
    endif()
endif()
if(MidnightBSD AND EXISTS "/usr/bin/objdump")
    execute_process(COMMAND /bin/sh -c "/usr/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1"
                    OUTPUT_VARIABLE OBJDUMP_T_RESULT)
    if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
        message(STATUS "Found FBSD ${CMAKE_MATCH_1}")
        target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}")
    endif()
elseif(FreeBSD AND EXISTS "/usr/local/bin/objdump")
    execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1"
                    OUTPUT_VARIABLE OBJDUMP_T_RESULT)
    if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
        message(STATUS "Found FBSD ${CMAKE_MATCH_1}")
        target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}")
    endif()
elseif(DragonFly AND EXISTS "/usr/local/bin/objdump")
    execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'DF[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1"
                    OUTPUT_VARIABLE OBJDUMP_T_RESULT)
    if("${OBJDUMP_T_RESULT}" MATCHES "DF([0-9]+\\.[0-9]+)")
        message(STATUS "Found DF ${CMAKE_MATCH_1}")
        target_compile_definitions(libfastfetch PUBLIC FF_DF_VERSION="${CMAKE_MATCH_1}")
    endif()
endif()

if(LINUX)
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _ATFILE_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _TIME_BITS=64) # "$<$<CONFIG:Release>:_FORTIFY_SOURCE=3>"
elseif(ANDROID)
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _FILE_OFFSET_BITS=64 "$<$<CONFIG:DEBUG>:__BIONIC_FORTIFY>" "$<$<CONFIG:DEBUG>:__BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED>")
elseif(WIN32)
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN WINRT_LEAN_AND_MEAN _WIN32_WINNT=0x0A00 NOMINMAX UNICODE) # "$<$<CONFIG:Release>:_FORTIFY_SOURCE=3>"
elseif(APPLE)
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _DARWIN_C_SOURCE)
elseif(OpenBSD)
    target_compile_definitions(libfastfetch PUBLIC _XOPEN_SOURCE=700 _FILE_OFFSET_BITS=64 _BSD_SOURCE)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/usr/X11R6/lib") # detect x11 lib path automatically
elseif(DragonFly)
    target_compile_definitions(libfastfetch PUBLIC __FreeBSD__)
elseif(SunOS)
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 __EXTENSIONS__ _POSIX_C_SOURCE)
elseif(NetBSD)
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-char-subscripts")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/usr/X11R7/lib -Wl,-rpath,/usr/pkg/lib") # ditto
elseif(Haiku)
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
elseif(GNU)
    # On Hurd PATH_MAX is not defined. Set an arbitrary limit as workaround.
    target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE PATH_MAX=4096 O_PATH=O_NORW)
endif()

if(APPLE)
    if(ENABLE_APPLE_MEMSIZE_USABLE)
        target_compile_definitions(libfastfetch PUBLIC FF_APPLE_MEMSIZE_USABLE=1)
    else()
        target_compile_definitions(libfastfetch PUBLIC FF_APPLE_MEMSIZE_USABLE=0)
    endif()
endif()

if(WIN32)
    check_function_exists(_msize HAVE_MSVC_MSIZE)
    if(HAVE_MSVC_MSIZE)
        target_compile_definitions(libfastfetch PUBLIC FF_HAVE_MSVC_MSIZE=1)
    endif()

    if(ENABLE_WIN81_COMPAT)
        target_compile_definitions(libfastfetch PUBLIC FF_WIN81_COMPAT=1)
    else()
        target_compile_definitions(libfastfetch PUBLIC FF_WIN81_COMPAT=0)
    endif()
else()
    check_function_exists(malloc_usable_size HAVE_MALLOC_USABLE_SIZE)
    if(HAVE_MALLOC_USABLE_SIZE)
        target_compile_definitions(libfastfetch PUBLIC FF_HAVE_MALLOC_USABLE_SIZE=1)
    else()
        check_function_exists(malloc_size HAVE_MALLOC_SIZE)
        if(HAVE_MALLOC_SIZE)
            target_compile_definitions(libfastfetch PUBLIC FF_HAVE_MALLOC_SIZE=1)
        endif()
    endif()
endif()

if(FreeBSD OR OpenBSD OR NetBSD)
    include(CheckStructHasMember)
    set(CMAKE_REQUIRED_DEFINITIONS "-D_IFI_OQDROPS=1")
    CHECK_STRUCT_HAS_MEMBER("struct if_data" ifi_oqdrops net/if.h HAVE_IFI_OQDROPS LANGUAGE C)
    if(HAVE_IFI_OQDROPS)
    target_compile_definitions(libfastfetch PUBLIC _IFI_OQDROPS FF_HAVE_IFI_OQDROPS)
    endif()
    unset(CMAKE_REQUIRED_DEFINITIONS)
endif()

if(HAVE_PIPE2)
    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_PIPE2)
endif()

if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
    message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
    target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
endif()
if(NOT "${CUSTOM_AMDGPU_IDS_PATH}" STREQUAL "")
    message(STATUS "Custom file path of amdgpu.ids: ${CUSTOM_AMDGPU_IDS_PATH}")
    target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_AMDGPU_IDS_PATH=${CUSTOM_AMDGPU_IDS_PATH})
endif()
if(NOT "${CUSTOM_OS_RELEASE_PATH}" STREQUAL "")
    message(STATUS "Custom file path of os_release: ${CUSTOM_OS_RELEASE_PATH}")
    target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
endif()
if(NOT "${CUSTOM_LSB_RELEASE_PATH}" STREQUAL "")
    message(STATUS "Custom file path of lsb_release: ${CUSTOM_LSB_RELEASE_PATH}")
    target_compile_definitions(libfastfetch PUBLIC FF_CUSTOM_LSB_RELEASE_PATH=${CUSTOM_LSB_RELEASE_PATH})
endif()

if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
    message(STATUS "Enabling custom link type: ${BINARY_LINK_TYPE}")
    target_compile_definitions(libfastfetch PUBLIC FF_DISABLE_DLOPEN=1)
    if(NOT WIN32)
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--copy-dt-needed-entries")
    endif()
endif()

function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME) # [CMAKE_TARGET_NAME]
    if(NOT ENABLE_${VARNAME})
        return()
    endif()

    if(PKG_CONFIG_FOUND)
        pkg_search_module(${VARNAME} QUIET ${PKGCONFIG_NAMES})
        if(${VARNAME}_FOUND)
            set(${VARNAME}_FOUND "pkg-config")
        endif()
    endif()

    if(NOT ${VARNAME}_FOUND)
        find_package(${CMAKE_NAME} QUIET)

        set(${VARNAME}_FOUND ${${CMAKE_NAME}_FOUND})
        if(${VARNAME}_FOUND)
            set(${VARNAME}_FOUND "CMake")

            # Some CMake packages (e.g. quickjs) are target-based only and
            # don't expose *_INCLUDE_DIRS/*_LIBRARIES variables.
            if(ARGC GREATER 3)
                set(_FF_CMAKE_TARGET ${ARGV3})
                if(NOT _FF_CMAKE_TARGET STREQUAL "")
                    if(NOT DEFINED ${VARNAME}_INCLUDE_DIRS OR "${${VARNAME}_INCLUDE_DIRS}" STREQUAL "")
                        get_target_property(_FF_CMAKE_TARGET_INCLUDES ${_FF_CMAKE_TARGET} INTERFACE_INCLUDE_DIRECTORIES)
                        if(_FF_CMAKE_TARGET_INCLUDES)
                            set(${VARNAME}_INCLUDE_DIRS ${_FF_CMAKE_TARGET_INCLUDES})
                        endif()
                    endif()

                    if(NOT DEFINED ${VARNAME}_LIBRARIES OR "${${VARNAME}_LIBRARIES}" STREQUAL "")
                        get_target_property(_FF_CMAKE_TARGET_LIBRARIES ${_FF_CMAKE_TARGET} INTERFACE_LINK_LIBRARIES)
                        if(_FF_CMAKE_TARGET_LIBRARIES)
                            set(${VARNAME}_LIBRARIES ${_FF_CMAKE_TARGET_LIBRARIES})
                        else()
                            set(${VARNAME}_LIBRARIES ${_FF_CMAKE_TARGET})
                        endif()
                    endif()

                    if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
                        # INTERFACE_LINK_LIBRARIES doesn't expose libvarname.a
                        target_link_libraries(libfastfetch PRIVATE ${_FF_CMAKE_TARGET})
                    endif()
                endif()
            else()
                set(${VARNAME}_INCLUDE_DIRS ${${CMAKE_NAME}_INCLUDE_DIRS})
                set(${VARNAME}_LIBRARIES ${${CMAKE_NAME}_LIBRARIES})
                set(${VARNAME}_CFLAGS_OTHER ${${CMAKE_NAME}_CFLAGS_OTHER})
            endif()
        endif()
    endif()

    if(NOT ${VARNAME}_FOUND)
        message(STATUS "Library: missing: ${VARNAME}")
        return()
    endif()

    message(STATUS "Library: found ${VARNAME} by ${${VARNAME}_FOUND}")

    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_${VARNAME}=1)
    target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})

    if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
        target_link_directories(libfastfetch PRIVATE ${${VARNAME}_LIBRARY_DIRS})
        target_link_libraries(libfastfetch PRIVATE ${${VARNAME}_LIBRARIES})
    endif()

    foreach(FLAG ${${VARNAME}_CFLAGS_OTHER})
        if(FLAG MATCHES "-D.*")
            string(SUBSTRING ${FLAG} 2 -1 FLAG)
            target_compile_definitions(libfastfetch PUBLIC ${FLAG})
        endif()
    endforeach()
endfunction()

ff_lib_enable(VULKAN
    "vulkan"
    "Vulkan"
)
ff_lib_enable(WAYLAND
    "wayland-client"
    "WaylandClient"
)
ff_lib_enable(XCB_RANDR
    "xcb-randr"
    "XcbRandr"
)
ff_lib_enable(XRANDR
    "xrandr"
    "XRandr"
)
ff_lib_enable(DRM
    "libdrm"
    "Libdrm"
)
ff_lib_enable(VADRM
    "libva-drm"
    "Libva-drm"
)
ff_lib_enable(VAX11
    "libva-x11"
    "Libva-x11"
)
ff_lib_enable(VDPAU
    "vdpau"
    "vdpau"
)
ff_lib_enable(GIO
    "gio-2.0"
    "GIO"
)
ff_lib_enable(DCONF
    "dconf"
    "DConf"
)
ff_lib_enable(EET
    "eet"
    "Eet"
)
ff_lib_enable(DBUS
    "dbus-1"
    "DBus"
)
ff_lib_enable(SQLITE3
    "sqlite3"
    "SQLite3"
)
ff_lib_enable(RPM
    "rpm"
    "RPM"
)
ff_lib_enable(IMAGEMAGICK7
    "MagickCore-7.Q16HDRI;MagickCore-7.Q16;MagickCore-7;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.pc"
    "ImageMagick7"
)
ff_lib_enable(IMAGEMAGICK6
    "MagickCore-6.Q16HDRI;MagickCore-6.Q16;MagickCore-6;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.pc"
    "ImageMagick6"
)
ff_lib_enable(ZLIB
    "zlib"
    "ZLIB"
)
ff_lib_enable(CHAFA
    "chafa>=1.10"
    "Chafa"
)
ff_lib_enable(EGL
    "egl"
    "EGL"
)
if(NOT OpenBSD AND NOT NetBSD)
    ff_lib_enable(GLX
        "glx"
        "GLX"
    )
else()
    ff_lib_enable(GLX
        "gl"
        "GL"
    )
endif()
ff_lib_enable(OPENCL
    "OpenCL"
    "OpenCL"
)
ff_lib_enable(FREETYPE
    "freetype2"
    "FreeType2"
)
ff_lib_enable(PULSE
    "libpulse"
    "Pulse"
)
ff_lib_enable(DDCUTIL
    "ddcutil"
    "Ddcutil"
)
ff_lib_enable(ELF
    "libelf"
    "libelf"
)
ff_lib_enable(QUICKJS
    "qjs"
    "qjs"
    "qjs"
)
if(ENABLE_LUA)
    # Lua is a special case since its CMake config does not follow the usual pattern
    find_package(Lua QUIET)
    if(Lua_FOUND AND NOT DEFINED Lua_VERSION) # For CMake 4.2- compatible
        set(Lua_VERSION ${LUA_VERSION_STRING})
        set(Lua_VERSION_MAJOR ${LUA_VERSION_MAJOR})
        set(Lua_VERSION_MINOR ${LUA_VERSION_MINOR})
    endif()
    if(Lua_FOUND)
        if((NOT Lua_VERSION_MAJOR EQUAL 5) OR Lua_VERSION_MINOR LESS 3 OR Lua_VERSION_MINOR GREATER 5)
            message(STATUS "Library: Lua version ${Lua_VERSION} is not supported, requires 5.3-5.5")
            unset(Lua_FOUND)
        else()
            target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LUA=1)
            target_include_directories(libfastfetch PUBLIC ${LUA_INCLUDE_DIR})

            if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
                target_link_libraries(libfastfetch PRIVATE ${LUA_LIBRARIES})
            endif()
            message(STATUS "Library: found LUA ${Lua_VERSION} by CMake")
        endif()
    else()
        message(STATUS "Library: missing: LUA")
    endif()
endif()

if(ENABLE_THREADS)
    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_THREADS=1)
    if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32
        target_link_libraries(libfastfetch PRIVATE Threads::Threads)
    endif()
endif()

if(ENABLE_EMBEDDED_PCIIDS)
    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_EMBEDDED_PCIIDS=1)
endif()
if(ENABLE_EMBEDDED_AMDGPUIDS)
    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_EMBEDDED_AMDGPUIDS=1)
endif()
if(ENABLE_LIBZFS)
    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LIBZFS=1)

    if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
        target_link_libraries(libfastfetch
            PRIVATE "zfs"
        )
    endif()
endif()
if(ENABLE_WCWIDTH)
    target_compile_definitions(libfastfetch PUBLIC FF_ENABLE_WCWIDTH=1)
endif()
if(NOT HAVE_MEMRCHR)
    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_CUSTOM_MEMRCHR=1)
endif()

if(LINUX)
    target_link_libraries(libfastfetch
        PRIVATE "m"
    )

    if(ENABLE_DIRECTX_HEADERS)
        if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
            target_link_libraries(libfastfetch
                PRIVATE "/usr/lib/wsl/lib/libdxcore.so"
            )
        endif()
    endif()
elseif(APPLE)
    target_link_libraries(libfastfetch
        PRIVATE "-framework AVFoundation"
        PRIVATE "-framework Cocoa"
        PRIVATE "-framework CoreFoundation"
        PRIVATE "-framework CoreAudio"
        PRIVATE "-framework CoreMedia"
        PRIVATE "-framework CoreVideo"
        PRIVATE "-framework CoreWLAN"
        PRIVATE "-framework IOBluetooth"
        PRIVATE "-framework IOKit"
        PRIVATE "-framework Metal"
        PRIVATE "-framework OpenGL"
        PRIVATE "-framework OpenCL"
        PRIVATE "-framework SystemConfiguration"
        PRIVATE "-framework VideoToolbox"
        PRIVATE "-weak_framework CoreDisplay"

        PRIVATE "-F /System/Library/PrivateFrameworks"
        PRIVATE "-weak_framework DisplayServices"
        PRIVATE "-weak_framework MediaRemote"
    )
elseif(WIN32)
    target_link_libraries(libfastfetch
        PRIVATE "gdi32"
        PRIVATE "iphlpapi"
        PRIVATE "ole32"
        PRIVATE "oleaut32"
        PRIVATE "ws2_32"
        PRIVATE "ntdll"
        PRIVATE "version"
        PRIVATE "hid"
        PRIVATE "wtsapi32"
        PRIVATE "cfgmgr32"
        PRIVATE "winbrand"
        PRIVATE "secur32"
    )
    if(NOT ENABLE_WIN81_COMPAT)
        target_link_libraries(libfastfetch
            PRIVATE "mincore"
        )
    endif()
    if(HAVE_WINRT)
        target_link_libraries(libfastfetch
            PRIVATE "runtimeobject"
        )
    endif()
    if(ENABLE_TRACER)
        target_link_libraries(libfastfetch
            PRIVATE "dbghelp"
        )
    endif()
elseif(FreeBSD)
    target_link_libraries(libfastfetch
        PRIVATE "m"
        PRIVATE "usbhid"
        PRIVATE "bluetooth"
    )
    if(NOT DragonFly)
        target_link_libraries(libfastfetch
            PRIVATE "geom"
        )
    else()
        target_link_libraries(libfastfetch
            PRIVATE "devstat"
        )
    endif()
elseif(OpenBSD)
    target_link_libraries(libfastfetch
        PRIVATE "m"
        PRIVATE "kvm"
        PRIVATE "sndio"
        PRIVATE "util"
    )
elseif(NetBSD)
    target_link_libraries(libfastfetch
        PRIVATE "bluetooth"
        PRIVATE "m"
        PRIVATE "prop"
        PRIVATE "util"
    )
elseif(SunOS)
    target_link_libraries(libfastfetch
        PRIVATE "m"
        PRIVATE "socket"
        PRIVATE "kstat"
        PRIVATE "proc"
        PRIVATE "devinfo"
    )
elseif(GNU)
    target_link_libraries(libfastfetch
        PRIVATE "m"
    )
elseif(ANDROID)
    target_link_libraries(libfastfetch
        PRIVATE "m"
    )
    if(ENABLE_WORDEXP)
        # https://github.com/termux/termux-packages/pull/7056
        CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
        if(HAVE_LIBANDROID_WORDEXP_STATIC)
            target_link_libraries(libfastfetch
                PRIVATE -l:libandroid-wordexp.a
            )
        else()
            CHECK_LIBRARY_EXISTS(android-wordexp wordexp "" HAVE_LIBANDROID_WORDEXP)
            if(HAVE_LIBANDROID_WORDEXP)
                target_link_libraries(libfastfetch
                    PRIVATE android-wordexp
                )
            endif()
        endif()
    endif()
elseif(Haiku)
    target_link_libraries(libfastfetch
        PRIVATE "network"
        PRIVATE "bnetapi"
        PRIVATE "media"
        PRIVATE "device"
        PRIVATE "bluetooth"
        PRIVATE "GL"
        PRIVATE "be"
        PRIVATE "gnu"
        PRIVATE "bsd"
    )
endif()

target_include_directories(libfastfetch
    PUBLIC ${PROJECT_BINARY_DIR}
    PUBLIC ${PROJECT_SOURCE_DIR}/src
)

target_link_libraries(libfastfetch
    PRIVATE ${CMAKE_DL_LIBS}
)

target_compile_options(libfastfetch PUBLIC
    $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti>)

if(FreeBSD)
    set(CMAKE_REQUIRED_INCLUDES "/usr/local/include" "/usr/include")
endif()
if(LINUX OR FreeBSD OR OpenBSD OR NetBSD)
    CHECK_INCLUDE_FILE("linux/videodev2.h" HAVE_LINUX_VIDEODEV2)
    if(HAVE_LINUX_VIDEODEV2)
        target_compile_definitions(libfastfetch PUBLIC FF_HAVE_LINUX_VIDEODEV2=1)
    endif()
endif()
if(NOT WIN32)
    CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX)
    if(HAVE_UTMPX)
        target_compile_definitions(libfastfetch PUBLIC FF_HAVE_UTMPX=1)
    endif()
    if(ENABLE_WORDEXP)
        CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
        if(HAVE_WORDEXP)
            target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WORDEXP=1)
            message(STATUS "wordexp.h found, wordexp support enabled")
        else()
            set(ENABLE_WORDEXP OFF)
        endif()
    endif()
    if(NOT ENABLE_WORDEXP)
        message(STATUS "wordexp.h not found or disabled, glob used instead")
    endif()
    if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT)
        CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
        if(HAVE_PTHREAD_NP)
            target_compile_definitions(libfastfetch PUBLIC FF_HAVE_PTHREAD_NP=1)
            set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} pthread_np.h)
        endif()
        set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} Threads::Threads)
        check_function_exists("pthread_timedjoin_np" HAVE_TIMEDJOIN_NP)
        if(HAVE_TIMEDJOIN_NP)
            target_compile_definitions(libfastfetch PUBLIC FF_HAVE_TIMEDJOIN_NP=1)
        else()
            message(WARNING "pthread_timedjoin_np was not found; networking timeout will not work")
        endif()
    endif()
elseif(HAVE_WINRT)
    target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WINRT=1)
endif()

set(PACKAGES_DISABLE_LIST "")
foreach(package_manager ${PACKAGE_MANAGERS})
    if(PACKAGES_DISABLE_${package_manager})
        list(APPEND PACKAGES_DISABLE_LIST "${package_manager}")
    endif()
endforeach()
if("${PACKAGES_DISABLE_LIST}" STREQUAL "")
    set(PACKAGES_DISABLE_LIST "FF_PACKAGES_FLAG_NONE")
else()
    message(STATUS "Disabled package managers: ${PACKAGES_DISABLE_LIST}")
    list(TRANSFORM PACKAGES_DISABLE_LIST PREPEND "FF_PACKAGES_FLAG_")
    list(TRANSFORM PACKAGES_DISABLE_LIST APPEND "_BIT")
    list(JOIN PACKAGES_DISABLE_LIST " | " PACKAGES_DISABLE_LIST)
endif()
target_compile_definitions(libfastfetch PUBLIC "FF_PACKAGES_DISABLE_LIST=${PACKAGES_DISABLE_LIST}")
if(PACKAGES_REMOVE_DISABLED)
    target_compile_definitions(libfastfetch PUBLIC FF_PACKAGES_REMOVE_DISABLED=1)
endif()

######################
# Executable targets #
######################

add_executable(fastfetch
    src/fastfetch.c
)
target_compile_definitions(fastfetch
    PRIVATE FASTFETCH_TARGET_BINARY_NAME=fastfetch
)
target_link_libraries(fastfetch
    PRIVATE libfastfetch
)

# Prevent fastfetch from linking to libstdc++
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)

if(WIN32)
    target_sources(fastfetch
        PRIVATE src/common/windows/version.rc
    )
elseif(APPLE)
    target_link_options(fastfetch
        PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
    )
endif()

if(BINARY_LINK_TYPE STREQUAL "static")
    target_link_options(fastfetch PRIVATE "-static")
endif()

# Apply all above parameters to flashfetch if it is built
if (BUILD_FLASHFETCH)
    add_executable(flashfetch
        src/flashfetch.c
    )
    target_compile_definitions(flashfetch
        PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
    )
    target_link_libraries(flashfetch
        PRIVATE libfastfetch
    )

    set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)

    if(WIN32)
        target_sources(flashfetch
            PRIVATE src/common/windows/version.rc
        )
    elseif(APPLE)
        target_link_options(flashfetch
            PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
        )
    endif()

    if(BINARY_LINK_TYPE STREQUAL "static")
        target_link_options(flashfetch PRIVATE "-static")
    endif()
endif()

###################
# Testing targets #
###################

if (BUILD_TESTS)
    add_executable(fastfetch-test-strbuf
        tests/strbuf.c
    )
    target_link_libraries(fastfetch-test-strbuf
        PRIVATE libfastfetch
    )

    add_executable(fastfetch-test-list
        tests/list.c
    )
    target_link_libraries(fastfetch-test-list
        PRIVATE libfastfetch
    )

    add_executable(fastfetch-test-format
        tests/format.c
    )
    target_link_libraries(fastfetch-test-format
        PRIVATE libfastfetch
    )

    add_executable(fastfetch-test-color
        tests/color.c
    )
    target_link_libraries(fastfetch-test-color
        PRIVATE libfastfetch
    )

    add_executable(fastfetch-test-duration
        tests/duration.c
    )
    target_link_libraries(fastfetch-test-duration
        PRIVATE libfastfetch
    )

    add_executable(fastfetch-test-strutil
        tests/strutil.c
    )
    target_link_libraries(fastfetch-test-strutil
        PRIVATE libfastfetch
    )

    enable_testing()
    add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
    add_test(NAME test-list COMMAND fastfetch-test-list)
    add_test(NAME test-format COMMAND fastfetch-test-format)
    add_test(NAME test-color COMMAND fastfetch-test-color)
    add_test(NAME test-duration COMMAND fastfetch-test-duration)
    add_test(NAME test-strutil COMMAND fastfetch-test-strutil)
endif()

##################
# install target #
##################

include(GNUInstallDirs)

install(
    TARGETS fastfetch
    DESTINATION "${CMAKE_INSTALL_BINDIR}"
)

if (TARGET flashfetch)
    install(
        TARGETS flashfetch
        DESTINATION "${CMAKE_INSTALL_BINDIR}"
    )
endif()

install(
    FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.bash"
    DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions"
    RENAME "${CMAKE_PROJECT_NAME}"
)

install(
    FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.zsh"
    DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/zsh/site-functions"
    RENAME "_${CMAKE_PROJECT_NAME}"
)

install(
    FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.fish"
    DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/fish/vendor_completions.d"
    RENAME "${CMAKE_PROJECT_NAME}.fish"
)

install(
    DIRECTORY "${CMAKE_SOURCE_DIR}/presets"
    DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}"
)

if(INSTALL_LICENSE)
    install(
        FILES "${CMAKE_SOURCE_DIR}/LICENSE"
        DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}"
    )
endif()

install(
    FILES "${PROJECT_BINARY_DIR}/fastfetch.1"
    DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
)

##################
# package target #
##################

set(CPACK_GENERATOR "TGZ;ZIP")
if(APPLE)
    string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) # use macos instead of darwin
elseif(IS_MUSL)
    string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
else()
    string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
endif()

if(LINUX)
    find_program(HAVE_DPKG "dpkg")
    if(HAVE_DPKG)
        set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB")

        set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
        set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")

        if(NOT IS_MUSL)
            EXECUTE_PROCESS(
                COMMAND getconf GNU_LIBC_VERSION
                OUTPUT_VARIABLE GLIBC_VERSION
                OUTPUT_STRIP_TRAILING_WHITESPACE)
            if(GLIBC_VERSION)
                STRING(REPLACE "glibc " "" GLIBC_VERSION ${GLIBC_VERSION})
                set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= ${GLIBC_VERSION})")
                message(STATUS "found glibc ${GLIBC_VERSION}")
            else()
                message(WARNING "Could not determine glibc version. If `musl` is used, `-DIS_MUSL=ON` should be set")
            endif()
        endif()
    endif()

    if(NOT IS_MUSL)
        find_program(HAVE_RPMBUILD "rpmbuild")
        if(HAVE_RPMBUILD)
            set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")

            set(CPACK_RPM_PACKAGE_LICENSE "MIT")
        endif()
    endif()
elseif(FreeBSD AND NOT DragonFly)
    set(CPACK_FREEBSD_PACKAGE_LICENSE "MIT")
    set(CPACK_GENERATOR "${CPACK_GENERATOR};FREEBSD")
endif()

set(CPACK_SET_DESTDIR ON)

set(CPACK_PACKAGE_CONTACT "Carter Li <zhangsongcui@live.cn>")
set(CPACK_PACKAGE_DESCRIPTION "\
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
It is written mostly in C to achieve much better performance.\
")

include(CPack)
