#=========================== begin_copyright_notice ============================
#
# Copyright (C) 2017-2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
#============================ end_copyright_notice =============================


# CMake settings:
#  - IGC_OPTION__LIBRARY_NAME
#FCL
#  - FCL_OPTION__LIBRARY_NAME
#  - IGC_OPTION__ARCHITECTURE_HOST
#  - IGC_OPTION__ARCHITECTURE_TARGET
#  - IGC_OPTION__BIF_LINK_BC
#  - IGC_OPTION__INCLUDE_IGC_COMPILER_TOOLS
#  - IGC_OPTION__OUTPUT_DIR

cmake_minimum_required(VERSION 3.13.4 FATAL_ERROR)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# Default languages: C, C++.
project(IGC)

if(UNIX)
  include(GNUInstallDirs)
endif()



# Increment IGC_API_MAJOR_VERSION if there is ABI Change.
if(NOT DEFINED IGC_API_MAJOR_VERSION)
  set(IGC_API_MAJOR_VERSION 1)
endif()
if(NOT DEFINED IGC_API_MINOR_VERSION)
  set(IGC_API_MINOR_VERSION 0)
endif()
# IGC_API_PATCH_VERSION
if(DEFINED IGC_PACKAGE_RELEASE)
      set(IGC_API_PATCH_VERSION ${IGC_PACKAGE_RELEASE})
else()
      set(IGC_API_PATCH_VERSION 1)
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

# ======================================================================================================
# ================================================ UTILS ===============================================
# ======================================================================================================


list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)

include(igc_flags_utils)
include(igc_arch_utils)
include(igc_resource_utils)
include(igc_source_group_utils)
include(igc_llvm_utils)

# ======================================================================================================
# ======================================================================================================
# ======================================================================================================



# ======================================================================================================
# ==================================== BUILD CONFIGURATIONS (part 1) ===================================
# ======================================================================================================

# IGC project available configuration types:
set(IGC_CMAKE_CONFIGURATION_TYPES
  "Debug"
  "Release"
)
set(IGC_CMAKE_CONFIGURATION_TYPES ${IGC_CMAKE_CONFIGURATION_TYPES} CACHE STRING "IGC available build configurations." FORCE)

if(CMAKE_CONFIGURATION_TYPES)
  # Multi-configuration generator: use CMAKE_CONFIGURATION_TYPES variable
  set(CMAKE_CONFIGURATION_TYPES ${IGC_CMAKE_CONFIGURATION_TYPES})

  if(CMAKE_BUILD_TYPE)
    message(FATAL_ERROR "CMAKE_BUILD_TYPE variable is not allowed while using multi-configuration generator!")
  endif()
else()
  # Single-configuration generator: use CMAKE_BUILD_TYPE variable
  if(DEFINED CMAKE_BUILD_TYPE)
    string(TOLOWER "${CMAKE_BUILD_TYPE}" _buildType)
    string(STRIP "${_buildType}" _buildType)

    if(_buildType MATCHES "^release$")
      set(_buildType "Release")
    elseif(_buildType MATCHES "^debug$")
      set(_buildType "Debug")
    else()
      set(_buildType "Release")
      message(WARNING "CMAKE_BUILD_TYPE: Unknown build configuration. The following configurations are available: ${IGC_CMAKE_CONFIGURATION_TYPES}.\nThe \"${_buildType}\" configuration will be used.\nThis value has meaning only for single-configuration generators (like Make). It will be ignored for MSVC/XCode.")
    endif()
  else()
    set(_buildType "Release")
    message(WARNING "CMAKE_BUILD_TYPE: No build configuration specified. The following configurations are available: ${IGC_CMAKE_CONFIGURATION_TYPES}.\nThe \"${_buildType}\" configuration will be used.\nThis value has meaning only for single-configuration generators (like Make). It will be ignored for MSVC/XCode.")
  endif()
  set(CMAKE_BUILD_TYPE "${_buildType}")
  unset(_buildType)
endif()

# Patterns which identify debug and release configurations.
set(IGC_BUILD__DEBUG_PATTERN   "^Debug$")
set(IGC_BUILD__RELEASE_PATTERN "^Release$")

# The configuration variables used below are likely to have been most recently
# defined by the project statement's call to the toolchain file
# ${CMAKE_TOOLCHAIN_FILE}.

# Some known cmake variables describing compiler:
# - CMAKE_CXX_COMPILER_ID == "Clang..." -> Clang
# - CMAKE_CXX_COMPILER_ID == "GNU"   -> GCC
# - CMAKE_CXX_COMPILER_ID == "Intel" -> Intel C++
# - CMAKE_CXX_COMPILER_ID == "MSVC"  -> using Visual Studio C++

# Local variables describing compilers:
# _igc_compiler_is_gnu       - C/C++ is gcc/g++ (not clang)
# _igc_compiler_is_clang     - C/C++ is clang/clang++ (not gcc/g++)
# _igc_compiler_is_gnu_or_clang  = C/C++ is either gnu or clang

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  set(_igc_compiler_is_gnu 1)
else()
  set(_igc_compiler_is_gnu 0)
endif()

if((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
  set(_igc_compiler_is_clang 1)
else()
  set(_igc_compiler_is_clang 0)
endif((CMAKE_C_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))

if(_igc_compiler_is_gnu OR _igc_compiler_is_clang)
  set(_igc_compiler_is_gnu_or_clang 1)
else()
  set(_igc_compiler_is_gnu_or_clang 0)
endif(_igc_compiler_is_gnu OR _igc_compiler_is_clang)

#
#  First, Set IGC_OPTION__ARCHITECTURE_TARGET, IGC_OPTION__ARCHITECTURE_HOST,
#  and IGC_BUILD__CROSSCOMPILE_NEEDED.
#
igc_arch_detect(IGC_BUILD__DETECTED_ARCHITECTURE_TARGET IGC_BUILD__DETECTED_ARCHITECTURE_HOST)
igc_arch_validate(_detectedTargetArchValid "${IGC_BUILD__DETECTED_ARCHITECTURE_TARGET}")
igc_arch_validate(_detectedHostArchValid   "${IGC_BUILD__DETECTED_ARCHITECTURE_HOST}")

if(DEFINED IGC_OPTION__ARCHITECTURE_TARGET)
  igc_arch_normalize(_targetArchitecture "${IGC_OPTION__ARCHITECTURE_TARGET}")
elseif(_detectedTargetArchValid)
  set(_targetArchitecture "${IGC_BUILD__DETECTED_ARCHITECTURE_TARGET}")
  message(WARNING "IGC_OPTION__ARCHITECTURE_TARGET: Target architecture is not specified. Trying to deduce it from context.")
else()
  message(FATAL_ERROR "IGC_OPTION__ARCHITECTURE_TARGET: Target architecture is not specified and cannot be deduced from context.\nPlease specify one, e.g. Windows32, Linux64, Android32, ...")
endif()

if(DEFINED IGC_OPTION__ARCHITECTURE_HOST)
  igc_arch_normalize(_hostArchitecture "${IGC_OPTION__ARCHITECTURE_HOST}")
elseif(_detectedHostArchValid)
  set(_hostArchitecture "${IGC_BUILD__DETECTED_ARCHITECTURE_HOST}")
  if(CMAKE_CROSSCOMPILING)
    message(WARNING "IGC_OPTION__ARCHITECTURE_HOST: Host architecture is not specified. Trying to deduce it from context.")
  endif()
elseif(CMAKE_CROSSCOMPILING)
  message(FATAL_ERROR "IGC_OPTION__ARCHITECTURE_HOST: Host architecture is not specified and cannot be deduced from context.\nPlease specify one, e.g. Windows32, Linux64, Android32, ...")
else()
  set(_hostArchitecture "${_targetArchitecture}")
endif()

igc_arch_crosscompile_needed(IGC_BUILD__CROSSCOMPILE_NEEDED "${_targetArchitecture}" "${_hostArchitecture}")

set(IGC_OPTION__ARCHITECTURE_TARGET "${_targetArchitecture}" CACHE STRING "Target architecture for compilation." FORCE)
set(IGC_OPTION__ARCHITECTURE_HOST   "${_hostArchitecture}"   CACHE STRING "Architecture of host used during compilation. Only used when cross-compiling." FORCE)
unset(_detectedTargetArchValid)
unset(_detectedHostArchValid)
unset(_targetArchitecture)
unset(_hostArchitecture)


# GFX_DEVELOPMENT_DIR shall be provided by UFO build system
if(NOT GFX_DEVELOPMENT_DIR)
  get_filename_component(GFX_DEVELOPMENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../ ABSOLUTE)
endif()

find_program(PYTHON_EXECUTABLE NAMES "python3" "python")

set(IGC_CODEGEN_BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}/autogen")
if(MSVC_IDE)
    set(IGC_CODEGEN_DIR "${IGC_CODEGEN_BASE_DIR}/${IGC_CMAKE_CFG_INTDIR}")
elseif(MSVC)
    set(IGC_CODEGEN_DIR "${IGC_CODEGEN_BASE_DIR}/${IGC_CMAKE_CFG_INTDIR}")
else()
    set(IGC_CODEGEN_DIR "${IGC_CODEGEN_BASE_DIR}")
endif()
add_subdirectory(MDAutogen ${IGC_CODEGEN_BASE_DIR}/MDAutogen)
set_source_files_properties(${IGC_CODEGEN_DIR}/MDNodeFunctions.gen PROPERTIES GENERATED TRUE)


# ============================================================================
# ========== BUILD CONFIGURATIONS (part 2) ===================================
# ============================================================================
# The section must be after project definition and its supported languages because otherwise
# used variables are not available yet.


# Populating global property with list of debug configurations (based on pattern).
set(_debugConfigs)
foreach(_configName ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
  if(_configName MATCHES "${IGC_BUILD__DEBUG_PATTERN}")
    list(APPEND _debugConfigs "${_configName}")
  endif()
endforeach()
set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS ${_debugConfigs})
unset(_debugConfigs)

# ======================================================================================================
# ======================================================================================================
# ======================================================================================================


# ======================================================================================================
# ========================================= BUILD CMAKE OPTIONS ========================================
# ======================================================================================================

if(DEFINED IGC_OPTION__LIBRARY_NAME)
  set(IGC_LIBRARY_NAME "${IGC_OPTION__LIBRARY_NAME}")
else()
  set(IGC_LIBRARY_NAME "igc")
endif()
set(IGC_LIBRARY_NAME ${IGC_LIBRARY_NAME} PARENT_SCOPE)

#FCL

if(DEFINED FCL_OPTION__LIBRARY_NAME)
  set(FCL_LIBRARY_NAME "${FCL_OPTION__LIBRARY_NAME}")
else()
  set(FCL_LIBRARY_NAME "igdfcl")
endif()
set(FCL_LIBRARY_NAME ${FCL_LIBRARY_NAME} PARENT_SCOPE)


set(_allowBifLink ON)


set(IGC_OPTION__BIF_LINK_BC ${_allowBifLink} CACHE BOOL "Built-in Functions: Link .bc files into final shared libraries.")
mark_as_advanced(IGC_OPTION__BIF_LINK_BC)
unset(_allowBifLink)


# Currently IGC uses 2 legacy SPIRV-LLVM-Translators
# First one is located at gfx-driver/Source/IGC/AdaptorOCL/SPIRV
# Second one is taken as prebuilt shared library called SPIRVDLL
# These translators will be replaced with vanilla Khronos translator.
# The following cmake code perfoms search for the such translator.
# But, until the transition is not completed, this code is under IGC_OPTION__LINK_KHRONOS_SPIRV_TRANSLATOR condition
# Remove this condition after transition period is over
option(IGC_OPTION__LINK_KHRONOS_SPIRV_TRANSLATOR "[Experimental] Enable link against Khronos SPIRV-LLVM-Translator, instead of legacy versions" OFF)
option(IGC_OPTION__USE_KHRONOS_SPIRV_TRANSLATOR_IN_VC "[Experimental] Enable usage of Khronos SPIRV-LLVM-Translator in Vector Compiler" OFF)
option(IGC_OPTION__USE_KHRONOS_SPIRV_TRANSLATOR_IN_SC "[Experimental] Enable usage of Khronos SPIRV-LLVM-Translator in Scalar Compiler" OFF)

option(IGC_OPTION__ENABLE_LIT_TESTS "Enable lit testing for IGC compiler. May require additional tools like llvm lit and opt" OFF)

set(IGC_OPTION__BIF_SRC_OCL_DIR "${IGC_SOURCE_DIR}/BiFModule"
    CACHE PATH "Built-in Functions: Root directory where sources for OpenCL builtins are located.")
mark_as_advanced(IGC_OPTION__BIF_SRC_OCL_DIR)

if(IGC_BUILD__CROSSCOMPILE_NEEDED AND (NOT CMAKE_CROSSCOMPILING))
  message(FATAL_ERROR "IGC_OPTION__ARCHITECTURE_TARGET,\nIGC_OPTION__ARCHITECTURE_HOST: Current target / host architecture combination requires cross-compiling. Please specify correct toolchain.")
endif()

igc_arch_validate(_archValid "${IGC_OPTION__ARCHITECTURE_TARGET}")
if(NOT _archValid)
  message(FATAL_ERROR "IGC_OPTION__ARCHITECTURE_TARGET: Target architecture \"${IGC_OPTION__ARCHITECTURE_TARGET}\" is invalid.\nPlease specify correct one, e.g. Windows32, Linux64, Android32, ...")
endif()
igc_arch_validate(_archValid "${IGC_OPTION__ARCHITECTURE_HOST}")
if(NOT _archValid)
  message(FATAL_ERROR "IGC_OPTION__ARCHITECTURE_HOST: Host architecture \"${IGC_OPTION__ARCHITECTURE_HOST}\" is invalid.\nPlease specify correct one, e.g. Windows32, Linux64, Android32, ...")
endif()


set(IGC_OPTION__IST_IGCC_ONLY ON CACHE BOOL
    "Only building igcc part of IST (IGCStandalone).")

set(IGC_OPTION__BUILD_IGC_OPT ON CACHE BOOL "Build project igc_opt.")

igc_arch_get_cpu(_cpuSuffix)
if(NOT DEFINED IGC_OPTION__OUTPUT_DIR)
set(IGC_OPTION__OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}" CACHE PATH "Output directory path where the final libraries will be stored.")
endif()
get_filename_component(IGC_OPTION__OUTPUT_DIR ${IGC_OPTION__OUTPUT_DIR} ABSOLUTE)
unset(_cpuSuffix)

if(NOT DEFINED IGC_OPTION__INCLUDE_IGC_COMPILER_TOOLS)
    set(IGC_OPTION__INCLUDE_IGC_COMPILER_TOOLS OFF)
endif()

set(IGC_OPTION__COMPILE_LINK_ALLOW_UNSAFE_SIZE_OPT ON CACHE BOOL "Compile/link: Allow unsafe size optimization like --gc-sections.")
mark_as_advanced(IGC_OPTION__COMPILE_LINK_ALLOW_UNSAFE_SIZE_OPT)

# IGC install time absolute path
if(IGC_OPTION__INSTALL_TIME_ROOT_DIR)
    get_filename_component(IGC_INSTALL_TIME_ROOT_DIR ${IGC_OPTION__INSTALL_TIME_ROOT_DIR} ABSOLUTE)
else()
    set(IGC_INSTALL_TIME_ROOT_DIR ${CMAKE_INSTALL_PREFIX})
endif()

# ============================================= Status =================================================

message(STATUS "================================ IGC Project ================================")
if(CMAKE_CONFIGURATION_TYPES)
    message(STATUS "Build types: ${CMAKE_CONFIGURATION_TYPES} (multi-configuration generator)")
else()
    message(STATUS "Build type:  ${CMAKE_BUILD_TYPE} (single-configuration generator)")
endif()
message(STATUS "Build tools: ${IGC_OPTION__INCLUDE_IGC_COMPILER_TOOLS}")
message(STATUS "LLVM dir:    ${IGC_OPTION__LLVM_DUMP_DIR}")
message(STATUS "")
message(STATUS "Output directory:")
message(STATUS "   \"${IGC_OPTION__OUTPUT_DIR}\"")
message(STATUS "Install root directory:")
message(STATUS "   \"${IGC_INSTALL_TIME_ROOT_DIR}\"")
message(STATUS "Architecture:")
message(STATUS " - target: ${IGC_OPTION__ARCHITECTURE_TARGET}    (detected: ${IGC_BUILD__DETECTED_ARCHITECTURE_TARGET})")
message(STATUS " - host:   ${IGC_OPTION__ARCHITECTURE_HOST}    (detected: ${IGC_BUILD__DETECTED_ARCHITECTURE_HOST})")
message(STATUS "")
message(STATUS "Cross-compilation needed: ${IGC_BUILD__CROSSCOMPILE_NEEDED}")
message(STATUS "Cross-compilation set:    ${CMAKE_CROSSCOMPILING}")
message(STATUS "")
message(STATUS "Advanced:")
message(STATUS " - Link BiF resources:              ${IGC_OPTION__BIF_LINK_BC}")
message(STATUS " - Building Windows Universal:      ${IGC_OPTION__UNIVERSAL_DRIVER}")
message(STATUS "=============================================================================")

# ======================================================================================================
# ======================================================================================================
# ======================================================================================================


# ======================================================================================================
# ======================================== COMPILE/LINK SETTINGS =======================================
# ======================================================================================================

# =========================================== Helper variables =========================================

# We are building IGC.
set(IGC_BUILD YES)


if(CMAKE_SYSTEM_NAME MATCHES "Windows")
  set(LLVM_ON_WIN32 ON)
else()
  set(LLVM_ON_WIN32 OFF)
endif()

# NOTE: LLVM_ON_UNIX is also true for Android (CMAKE_SYSTEM_NAME specified by Android toolchain file is also "Linux",
# but we should make sure so there is no errors in our assumptions).
if((CMAKE_SYSTEM_NAME MATCHES "Linux") OR ANDROID)
  set(LLVM_ON_UNIX ON)
else()
  set(LLVM_ON_UNIX OFF)
endif()


if(_igc_compiler_is_gnu_or_clang AND NOT IGC_BUILD_DISABLE_FLAGS_GNU_CLANG)
  set(IGC_BUILD__WHOLE_ARCHIVE    "-Wl,--whole-archive")
  set(IGC_BUILD__NO_WHOLE_ARCHIVE "-Wl,--no-whole-archive")
  set(IGC_BUILD__START_GROUP      "-Wl,--start-group")
  set(IGC_BUILD__END_GROUP        "-Wl,--end-group")
else()
  set(IGC_BUILD__WHOLE_ARCHIVE    "")
  set(IGC_BUILD__NO_WHOLE_ARCHIVE "")
  set(IGC_BUILD__START_GROUP      "")
  set(IGC_BUILD__END_GROUP        "")
endif()

set(IGC_BUILD__PROJ_NAME_PREFIX "")

#SPIRV consumption variable

set(IGC_BUILD__SPIRV_ENABLED ON)


# Enable vector compiler for Linux and Windows
# If user already defined this, honor decision
if(NOT DEFINED IGC_BUILD__VC_ENABLED)
  if(LLVM_ON_UNIX OR LLVM_ON_WIN32)
    set(IGC_BUILD__VC_ENABLED ON)
  endif()
endif()


# ======================================== Path helper variables =======================================

set(IGC_BUILD__IGC_SRC_DIR          "${IGC_SOURCE_DIR}")
set(IGC_BUILD__IGC_COMMON_DIR       "${IGC_BUILD__IGC_SRC_DIR}/common")


set(IGC_BUILD__IGC_BIN_DIR          "${IGC_BINARY_DIR}")

set(IGC_BUILD__GFX_DEV_SRC_DIR      "${IGC_SOURCE_DIR}/..")
set(IGC_BUILD__GFX_DEV_TOOLS_DIR    "${IGC_SOURCE_DIR}/../../Tools")

set(IGC_BUILD__COMMON_DIR           "${IGC_BUILD__GFX_DEV_SRC_DIR}/Common")
set(IGC_BUILD__3D_COMMON_DIR        "${IGC_BUILD__GFX_DEV_SRC_DIR}/3d/common")

set(IGC_BUILD__INC_DIR              "${IGC_BUILD__GFX_DEV_SRC_DIR}/inc")
set(IGC_BUILD__COMMON_COMPILER_DIR  "${IGC_BUILD__GFX_DEV_SRC_DIR}/inc/common/Compiler")
set(IGC_BUILD__VISA_DIR             "${IGC_BUILD__GFX_DEV_SRC_DIR}/visa")

set(IGC_BUILD__TOOLS_IGC_DIR        "${IGC_BUILD__GFX_DEV_TOOLS_DIR}/IGC")
set(IGC_BUILD__TOOLS_IST_DIR        "${IGC_BUILD__GFX_DEV_TOOLS_DIR}/IST")


set(IGC_BUILD__BIF_DIR              "${IGC_OPTION__OUTPUT_DIR}/bif/${IGC_CMAKE_CFG_INTDIR}")
set(IGC_BUILD__TOOLS_OUTPUT_DIR     "${IGC_OPTION__OUTPUT_DIR}/Tools")
set(IGC_BUILD__UNIT_TEST_OUTPUT_DIR "${IGC_OPTION__OUTPUT_DIR}/UnitTests")
set(IGC_BUILD__CTH_DIR              "${IGC_OPTION__OUTPUT_DIR}/fcl")

# Including CIF
set(CIF_BASE_DIR "AdaptorOCL/cif")
add_subdirectory("${CIF_BASE_DIR}/cif" ${CMAKE_CURRENT_BINARY_DIR}/cif)

# ================================================ Outputs =============================================

set(EXECUTABLE_OUTPUT_PATH ${IGC_OPTION__OUTPUT_DIR})
set(LIBRARY_OUTPUT_PATH    ${IGC_OPTION__OUTPUT_DIR})

# =============================== Compiler options (generic configuration) =============================

# Compiler options:
#   = - Equal
#   ^ - Implicitly defined by differnt option (like /O2).
#   ! - Should not be changed (should not be defined in first place -> there is no non-Windows support).
#   * - Needs to be modified in CMake.
#   + - Needs to be added in CMake.
#   - - Needs to be removed in CMake.
#
#   MSVC:
#     =/analyze-   =/EHsc   =/errorReport:prompt   =/fp:precise   =/Gd   =/Gm-   ^/GF    /GR-   ^/GS   ^/Gy    /MP    /MT   =/nologo   =/O2   ^/Ob2   ^/Oi    /Os   =/Oy-          =/W3   !/Zc:forScope-   =/Zc:wchar_t    /Zi    /Zp8
#     ?/wd"4146"   ?/wd"4355"   ?/wd"4800"   ?/wd"4482"   ?/wd"4244"   ?/WX
#   CMake:
#     =/analyze-   =/EHsc   =/errorReport:prompt   =/fp:precise   =/Gd   =/Gm-   ^/GF   */GR    ^/GS   ^/Gy   +/MP   */MD   =/nologo   =/O2   ^/Ob2   ^/Oi   +/Os   =/Oy-   -/TP   =/W3    /Zc:forScope    =/Zc:wchar_t   +/Zi   ^/Zp8
#                                                                      ?/WX-
#
#   Notes:
#    - "/Zc:forScope-" is non-standard behavior which is not portable to other OSes. It was defined for MFC and should not be used in modern code.
#    - "/Zp8" is default max. alignment for struct members (this option and its behavior can be hard to port to other OSes).
#    - "/wd" some of the warning are critically useful (especially when warning level is less than 4):
#      4146 -> this can lead to problems with comparison; limits or numeric_limits usually allow to quickly correct the code.
#      4244 -> this can lead to hard to catch problems with loss of data (especially when /W2 or /W3 type occurred and in x86_64 architetures).
#      4355 -> warning: "this" passed to base class should be off by default (what enabled this?).
#      4482 -> C++11 compilers allow enum qualification without warning (should not be problem since MSVC 2013).
#      4800 -> can be disabled but it can be corrected pretty quick.
#      4267 -> var : conversion from 'size_t' to 'type', possible loss of data
#      4273 -> function' : inconsistent DLL linkage
#    - "/WX" should be re-enabled when all warnings are cleaned from code.
#    - Although "/O1" is usual set of settings for optmimization for size, but "/O2" "/Oi" "/Os" is preferred in IGC.
#    - we want to disable warning 4267: conversion from 'size_t' to 'uint32_t', possible loss of data
#    - Adding warning 4062 to be emiited at level 1: enumerator 'identifier' in switch of enum 'enumeration' is not handled


if(MSVC)
  igc_flag_register_settings(
      CompilerOptions

      GROUP NAME CallingConvention  "/G[drzv]"
      GROUP NAME CompileAs          "/T[CP]"
      GROUP NAME DebugInfoFormat    "/Z[7iI]"
      GROUP NAME Exceptions         "/EHa" "/EHsc?"
      GROUP NAME FaviorSizeSpeed    "/O[st]"
      GROUP NAME Optimization       "/O[d12x]"
      GROUP NAME RuntimeLibrary     "/M[TD]d?"
      GROUP NAME Rtti               "/GR-?"
      GROUP NAME TreatWarnAsError   "/WX-?"

      ALIAS AdditionalOptions          "/w14062" "/Wv:18"
      ALIAS CallingConvCdecl           "/Gd"
      ALIAS CallingConvFastcall        "/Gr"
      ALIAS CallingConvStdcall         "/Gz"
      ALIAS CallingConvVectorcall      "/Gv"
      ALIAS CompileAsC                 "/TC"
      ALIAS CompileAsCpp               "/TP"
      ALIAS CompileAsDefault           CompileAs REMOVE_GROUP
      ALIAS DebugInfoDisabled          DebugInfoFormat REMOVE_GROUP
      ALIAS DebugInfoProgramDatabase   "/Zi"
      ALIAS DisableSpecificWarnings    "/wd4267" "/wd4273" "/wd4091" "/wd4996"
      ALIAS ExceptionsDisabled         Exceptions REMOVE_GROUP
      ALIAS ExceptionsEnabled          "/EHsc"
      ALIAS FaviorSize                 "/Os"
      ALIAS FaviorSpeed                "/Ot"
      ALIAS MultiProcessorCompilation  "/MP"
      ALIAS OptimizeDisabled           "/Od"
      ALIAS OptimizeSize               "/O2" "/Oi" "/Os"
      ALIAS OptimizeSpeed              "/O2" "/Oi" "/Ot"
      ALIAS OptimizeFull               "/Ox"
      ALIAS RtMultiThreadedStatic      "/MT"
      ALIAS RtMultiThreadedShared      "/MD"
      ALIAS RtMultiThreadedStaticDebug "/MTd"
      ALIAS RtMultiThreadedSharedDebug "/MDd"
      ALIAS RttiDisabled               "/GR-"
      ALIAS RttiEnabled                "/GR"
      ALIAS TreatWarnAsErrorDisabled   "/WX-"
      ALIAS TreatWarnAsErrorEnabled    "/WX"
      ALIAS UninitializedVarWarning    "/w14701"
      ALIAS UnreferencedVariable       "/w14189"
      ALIAS WholeProgramOptimization   "/GL"
      ALIAS ControlFlowGuard           "/guard:cf"

      ALIAS DeadCodeEliminate
      ALIAS DeadCodePreserve
    )
elseif(_igc_compiler_is_gnu)
  igc_flag_register_settings(
      CompilerOptions

      GROUP NAME DebugInfoFormat    "-g[0-3]?"
      GROUP NAME Exceptions         "-f(no-)?exceptions"
      GROUP NAME Optimization       "-O[0-3sg]?"
      GROUP NAME Rtti               "-f(no-)?rtti"
      GROUP NAME TreatWarnAsError   "-Werror"

      ALIAS AdditionalOptions
      ALIAS CallingConvCdecl
      ALIAS CallingConvFastcall
      ALIAS CallingConvStdcall
      ALIAS CallingConvVectorcall
      ALIAS CompileAsC
      ALIAS CompileAsCpp
      ALIAS CompileAsDefault
      ALIAS DebugInfoDisabled          "-g0"
      ALIAS DebugInfoProgramDatabase   "-g"
      ALIAS DisableSpecificWarnings
      ALIAS ExceptionsDisabled         "-fno-exceptions"
      ALIAS ExceptionsEnabled          "-fexceptions"
      ALIAS FaviorSize                 "-Os"
      ALIAS FaviorSpeed                "-O3"
      ALIAS MultiProcessorCompilation
      ALIAS OptimizeDisabled           "-O0"
      ALIAS OptimizeSize               "-Os"
      ALIAS OptimizeSpeed              "-O2"
      ALIAS OptimizeFull               "-O3"
      ALIAS RtMultiThreadedStatic
      ALIAS RtMultiThreadedShared
      ALIAS RtMultiThreadedStaticDebug
      ALIAS RtMultiThreadedSharedDebug
      ALIAS RttiDisabled               "-fno-rtti"
      ALIAS RttiEnabled                "-frtti"
      ALIAS TreatWarnAsErrorDisabled   TreatWarnAsError REMOVE_GROUP
      ALIAS TreatWarnAsErrorEnabled    "-Werror"
      ALIAS UnreferencedVariable
      ALIAS UninitializedVarWarning
      ALIAS WholeProgramOptimization
      ALIAS ControlFlowGuard

      ALIAS DeadCodeEliminate
      ALIAS DeadCodePreserve
    )

  if(IGC_OPTION__COMPILE_LINK_ALLOW_UNSAFE_SIZE_OPT)
    igc_flag_register_settings(
        CompilerOptions

        GROUP NAME EmitDataSec "-fdata-sections"
        GROUP NAME EmitFuncSec "-ffunction-sections"

        ALIAS DeadCodeEliminate  "-fdata-sections" "-ffunction-sections"
        ALIAS DeadCodePreserve   EmitDataSec EmitFuncSec REMOVE_GROUP
      )
  endif()
elseif(_igc_compiler_is_clang)
  igc_flag_register_settings(
      CompilerOptions

      GROUP NAME DebugInfoFormat    "-g(dwardf-[2-4]?)?"
      GROUP NAME Exceptions         "-f(no-)?exceptions"
      GROUP NAME Optimization       "-O([0-3]?|fast|s|z)?"
      GROUP NAME Rtti               "-f(no-)?rtti"
      GROUP NAME TreatWarnAsError   "-Werror"

      ALIAS AdditionalOptions
      ALIAS CallingConvCdecl
      ALIAS CallingConvFastcall
      ALIAS CallingConvStdcall
      ALIAS CallingConvVectorcall
      ALIAS CompileAsC
      ALIAS CompileAsCpp
      ALIAS CompileAsDefault
      ALIAS DebugInfoDisabled          DebugInfoFormat REMOVE_GROUP
      ALIAS DebugInfoProgramDatabase   "-g"
      ALIAS DisableSpecificWarnings
      ALIAS ExceptionsDisabled         Exceptions REMOVE_GROUP
      ALIAS ExceptionsEnabled          "-fexceptions"
      ALIAS FaviorSize                 "-Os"
      ALIAS FaviorSpeed                "-O3"
      ALIAS MultiProcessorCompilation
      ALIAS OptimizeDisabled           "-O0"
      ALIAS OptimizeSize               "-Os"
      ALIAS OptimizeSpeed              "-O2"
      ALIAS OptimizeFull               "-03"
      ALIAS RtMultiThreadedStatic
      ALIAS RtMultiThreadedShared
      ALIAS RtMultiThreadedStaticDebug
      ALIAS RtMultiThreadedSharedDebug
      ALIAS RttiDisabled               "-fno-rtti"
      ALIAS RttiEnabled                Rtti REMOVE_GROUP
      ALIAS TreatWarnAsErrorDisabled   TreatWarnAsError REMOVE_GROUP
      ALIAS TreatWarnAsErrorEnabled    "-Werror"
      ALIAS UnreferencedVariable
      ALIAS UninitializedVarWarning
      ALIAS WholeProgramOptimization
      ALIAS ControlFlowGuard

      ALIAS DeadCodeEliminate
      ALIAS DeadCodePreserve
    )
else()
  igc_flag_register_settings(
      CompilerOptions

      ALIAS AdditionalOptions
      ALIAS CallingConvCdecl
      ALIAS CallingConvFastcall
      ALIAS CallingConvStdcall
      ALIAS CallingConvVectorcall
      ALIAS CompileAsC
      ALIAS CompileAsCpp
      ALIAS CompileAsDefault
      ALIAS DebugInfoDisabled
      ALIAS DebugInfoProgramDatabase
      ALIAS DisableSpecificWarnings
      ALIAS ExceptionsDisabled
      ALIAS ExceptionsEnabled
      ALIAS FaviorSize
      ALIAS FaviorSpeed
      ALIAS MultiProcessorCompilation
      ALIAS OptimizeDisabled
      ALIAS OptimizeSize
      ALIAS OptimizeSpeed
      ALIAS OptimizeFull
      ALIAS RtMultiThreadedStatic
      ALIAS RtMultiThreadedShared
      ALIAS RtMultiThreadedStaticDebug
      ALIAS RtMultiThreadedSharedDebug
      ALIAS RttiDisabled
      ALIAS RttiEnabled
      ALIAS TreatWarnAsErrorDisabled
      ALIAS TreatWarnAsErrorEnabled
      ALIAS UnreferencedVariable
      ALIAS UninitializedVarWarning
      ALIAS WholeProgramOptimization
      ALIAS ControlFlowGuard

      ALIAS DeadCodeEliminate
      ALIAS DeadCodePreserve
    )
endif()

# ================================ Linker options (generic configuration) ==============================
if(MSVC)
  if(IGC_OPTION__UNIVERSAL_DRIVER)
    igc_flag_register_settings(
        LinkerOptions

        GROUP NAME DebugInfo         "/[dD][eE][bB][uU][gG]"
        GROUP NAME DeadCode          "/[oO][pP][tT]:([nN][oO])?[rR][eE][fF]"
        GROUP NAME IdenticalCodeData "/[oO][pP][tT]:([nN][oO])?[iI][cC][fF](=[0-9]+)?"

        ALIAS AdditionalOptions
        ALIAS DebugInfoDisabled          DebugInfo REMOVE_GROUP
        ALIAS DebugInfoProgramDatabase   "/DEBUG"
        ALIAS DeadCodeEliminate          "/OPT:REF"
        ALIAS DeadCodePreserve           "/OPT:NOREF"
        ALIAS IdenticalCodeDataFold      "/OPT:ICF"
        ALIAS IdenticalCodeDataNoFold    "/OPT:NOICF"
        ALIAS LinkTimeCodeGeneration     "/LTCG"
        ALIAS ControlFlowGuard           "/guard:cf"
        ALIAS NoDefaultLib               "/NODEFAULTLIB:kernel32.lib"
      )
  else()
    igc_flag_register_settings(
        LinkerOptions

        GROUP NAME DebugInfo         "/[dD][eE][bB][uU][gG]"
        GROUP NAME DeadCode          "/[oO][pP][tT]:([nN][oO])?[rR][eE][fF]"
        GROUP NAME IdenticalCodeData "/[oO][pP][tT]:([nN][oO])?[iI][cC][fF](=[0-9]+)?"

        ALIAS DebugInfoDisabled          DebugInfo REMOVE_GROUP
        ALIAS DebugInfoProgramDatabase   "/DEBUG"
        ALIAS DeadCodeEliminate          "/OPT:REF"
        ALIAS DeadCodePreserve           "/OPT:NOREF"
        ALIAS IdenticalCodeDataFold      "/OPT:ICF"
        ALIAS IdenticalCodeDataNoFold    "/OPT:NOICF"
        ALIAS LinkTimeCodeGeneration     "/LTCG"
        ALIAS ControlFlowGuard           "/guard:cf"
        ALIAS NoDefaultLib
      )
  endif()
else()
  igc_flag_register_settings(
      LinkerOptions

      ALIAS DebugInfoDisabled
      ALIAS DebugInfoProgramDatabase
      ALIAS DeadCodeEliminate
      ALIAS DeadCodePreserve
      ALIAS IdenticalCodeDataFold
      ALIAS IdenticalCodeDataNoFold
      ALIAS LinkTimeCodeGeneration
      ALIAS ControlFlowGuard
      ALIAS NoDefaultLib
    )

  if(IGC_OPTION__COMPILE_LINK_ALLOW_UNSAFE_SIZE_OPT)
    if(_igc_compiler_is_gnu_or_clang)
      igc_flag_register_settings(
          LinkerOptions

          GROUP NAME GcSections "-Wl,--gc-sections"

          ALIAS DeadCodeEliminate  "-Wl,--gc-sections"
          ALIAS DeadCodePreserve   GcSections REMOVE_GROUP
        )
    endif()
  endif()
endif()

# =========================================== Compiler options =========================================

foreach(_compilerFlagName IN ITEMS "CMAKE_CXX_FLAGS" "CMAKE_C_FLAGS")
  # Change some generic settings of compiler.
  # NOTE: Debug info generation is enabled for all build configuration, because it is separate on Windows
  #       and we will use "strip" command on Linux and Android (to separate it).

  if(IGC_OPTION__UNIVERSAL_DRIVER)
    igc_config_flag_apply_settings(
          CompilerOptions
          "${_compilerFlagName}"
          ALL_PATTERN ""
          SET
            CompileAsDefault
            DisableSpecificWarnings
            ExceptionsDisabled
            MultiProcessorCompilation
            DeadCodeEliminate
            CallingConvCdecl
    )
  else()
    igc_config_flag_apply_settings(
          CompilerOptions
          "${_compilerFlagName}"
          ALL_PATTERN ""
          SET
            CompileAsDefault

            DisableSpecificWarnings
            ExceptionsDisabled
            MultiProcessorCompilation
            DeadCodeEliminate
    )
  endif()

  igc_config_flag_apply_settings(
      CompilerOptions
      "${_compilerFlagName}"
      ALL_PATTERN_NOINHERIT ""
      SET
        DebugInfoProgramDatabase
        OptimizeSize
        RtMultiThreadedStatic
    )
  igc_config_flag_apply_settings(
      CompilerOptions
      "${_compilerFlagName}"
      PATTERN "${IGC_BUILD__DEBUG_PATTERN}"
      SET
        OptimizeDisabled
        RtMultiThreadedStaticDebug
        UnreferencedVariable
    )
  igc_config_flag_apply_settings(
      CompilerOptions
      "${_compilerFlagName}"
      PATTERN "${IGC_BUILD__RELEASE_PATTERN}"
      SET
        OptimizeSpeed
        ControlFlowGuard
        # Disable LTCG due to increase of release build time
        #WholeProgramOptimization
    )

  # Adding needed settings specific to MSVC.
  if(MSVC)
  # Adding needed settings specific to GCC.
  # NOTE: Following options can be needed in the future (although some not recommended: NR):
  # [NR] -fno-short-enums
  # [NR] -fno-tree-pre
  #      -fno-omit-frame-pointer
  #      -Wa,--noexecstack
  #      -fkeep-inline-functions
    igc_config_flag_apply_settings(
        CompilerOptions
        "${_compilerFlagName}"
        ALL_PATTERN ""
         SET
           AdditionalOptions
           RttiDisabled
           TreatWarnAsErrorEnabled
    )
  elseif( ANDROID )
    igc_config_flag_apply_settings(
        CompilerOptions
        "${_compilerFlagName}"
        ALL_PATTERN ""
        SET_RAW
          -pipe
          -fmessage-length=0
          -march=corei7
          -mstackrealign
          -fms-extensions
          -fvisibility=hidden
          -Werror
          -Wno-unused-parameter
          -Wno-missing-field-initializers
          -Wwrite-strings
          -Wno-long-long
          -Wswitch
          -Wno-sign-compare
          -Wno-unused-result
          -Wno-enum-compare
          -Wno-type-limits
          -Wno-ignored-qualifiers
          -Wno-format
          -Wno-format-security
          -Wno-extra
          -Wno-write-strings
          -finline
          -fno-strict-aliasing
          -msse
          -msse2
          -msse3
          -mssse3
          -msse4
          -msse4.1
          -msse4.2
          -Wno-unknown-pragmas
          -fPIC
    )
    if(_igc_compiler_is_gnu)
      igc_config_flag_apply_settings(
      CompilerOptions
      "${_compilerFlagName}"
      ALL_PATTERN ""
      SET_RAW
        -funswitch-loops
        -Wno-maybe-uninitialized
    )
    endif()
    if(_igc_compiler_is_gnu OR (_igc_compiler_is_clang AND NOT CMAKE_C_COMPILER_VERSION LESS "4.0"))
      igc_config_flag_apply_settings(
      CompilerOptions
      "${_compilerFlagName}"
      ALL_PATTERN ""
      SET_RAW
            -finline-functions
    )
    endif()

  elseif(_igc_compiler_is_gnu_or_clang)
    igc_config_flag_apply_settings(
        CompilerOptions
        "${_compilerFlagName}"
        ALL_PATTERN ""
        SET_RAW
          -pipe
          -fmessage-length=0
          -march=corei7
          -mstackrealign
          -fms-extensions
          -Werror
          -Wno-unused-parameter
          -Wno-missing-field-initializers
          -Wwrite-strings
          -Wno-long-long
          -Wswitch
          -Wno-sign-compare
          -Wno-unused-result
          -Wno-enum-compare
          -Wno-type-limits
          -Wno-ignored-qualifiers
          -Wno-shadow
          -Wformat
          -Wformat-security
          -Wno-extra
          -Wno-write-strings
          -finline
          -fno-strict-aliasing
          -msse
          -msse2
          -msse3
          -mssse3
          -msse4
          -msse4.1
          -msse4.2
          -Wno-unknown-pragmas
          -fPIC
    )
    igc_config_flag_apply_settings(
        CompilerOptions
        "${_compilerFlagName}"
        PATTERN "${IGC_BUILD__RELEASE_PATTERN}"
        SET_RAW
          -D_FORTIFY_SOURCE=2
          -fstack-protector
    )
    if(_igc_compiler_is_gnu OR (_igc_compiler_is_clang AND NOT CMAKE_C_COMPILER_VERSION LESS "4.0"))
      igc_config_flag_apply_settings(
          CompilerOptions
          "${_compilerFlagName}"
          ALL_PATTERN ""
          SET_RAW
            -finline-functions
      )
    endif()
    if(NOT _igc_compiler_is_clang)
      set(flags -funswitch-loops -Wno-maybe-uninitialized)
      if(NOT ANDROID)
        list(APPEND flags -lrt)
      endif()
      igc_config_flag_apply_settings(
          CompilerOptions
          "${_compilerFlagName}"
          ALL_PATTERN ""
          SET_RAW
            ${flags}
      )
    endif()
  elseif(_igc_compiler_is_clang)
    igc_config_flag_apply_settings(
        CompilerOptions
        "${_compilerFlagName}"
        ALL_PATTERN ""
        SET_RAW
        -pipe
        -fvisibility=hidden
        -fvisibility-inlines-hidden
        -Wcovered-switch-default
        -Wno-unused-parameter
        -Wno-gnu
        -finline
        -fkeep-inline-functions
        -msse4.2
    )
    if(NOT CMAKE_C_COMPILER_VERSION LESS "4.0")
      igc_config_flag_apply_settings(
          CompilerOptions
         "${_compilerFlagName}"
          ALL_PATTERN ""
          SET_RAW
            -finline-functions
      )
    endif()
  endif()
endforeach()

if( ANDROID OR _igc_compiler_is_gnu_or_clang)
  igc_config_flag_apply_settings(
      LinkerOptions
      CMAKE_SHARED_LINKER_FLAGS
      ALL_PATTERN ""
      SET_RAW
    -Wl,--no-undefined
    )
endif()

# NOTE: [WA] Workaround for OpenGL-IGC crash problem. Due to different handling of static objects destructors
#            the destructor of PassRegistry was called two times during exiting of OpenGL.
#            This switch is not conformant with C++ standard (order of destruction of static elements is not met) but
#            it is used in Android build system (possibliy due to Android bionic __cxa_atexit limitations).
if(_igc_compiler_is_gnu_or_clang)
  if(ANDROID)
    igc_config_flag_apply_settings(
        CompilerOptions
        CMAKE_CXX_FLAGS
        ALL_PATTERN ""
        SET_RAW
          -fno-use-cxa-atexit
          -fvisibility-inlines-hidden
          -fpermissive
          -fno-rtti
      )
  endif()
endif()

# Unconditionally disable rtti (C++ only)
igc_config_flag_apply_settings(
    CompilerOptions
    CMAKE_CXX_FLAGS
    ALL_PATTERN ""
    SET
       RttiDisabled
  )


if(_igc_compiler_is_gnu_or_clang)
    igc_config_flag_apply_settings(
        CompilerOptions
        CMAKE_CXX_FLAGS
        ALL_PATTERN ""
        SET_RAW
          -fvisibility=hidden
          -fvisibility-inlines-hidden
    )
endif()

# ============================================ Linker options ==========================================

foreach(_linkerFlagName IN ITEMS "CMAKE_EXE_LINKER_FLAGS" "CMAKE_SHARED_LINKER_FLAGS")
  # Change some generic settings of linker.
  # NOTE: Debug info generation is enabled for all build configuration, because it is separate on Windows
  #       and we will use "strip" command on Linux and Android (to separate it).

  igc_config_flag_apply_settings(
      LinkerOptions
      "${_linkerFlagName}"
      ALL_PATTERN ""
      SET
        DebugInfoProgramDatabase
        NoDefaultLib
    )

  igc_config_flag_apply_settings(
      LinkerOptions
      "${_linkerFlagName}"
      ALL_PATTERN_NOINHERIT ""
      SET
        DeadCodeEliminate
        IdenticalCodeDataFold
    )
    igc_config_flag_apply_settings(
      LinkerOptions
      "${_linkerFlagName}"
      PATTERN "${IGC_BUILD__RELEASE_PATTERN}"
      SET
        ControlFlowGuard
        # Disable LTCG due to release build time increase
        #LinkTimeCodeGeneration
    )
    igc_config_flag_apply_settings(
      LinkerOptions
      "${_linkerFlagName}"
      PATTERN "${IGC_BUILD__DEBUG_PATTERN}"
      SET
        DeadCodePreserve
        IdenticalCodeDataNoFold
    )
endforeach()

if(MSVC)
if(LLVM_VERSION_MAJOR EQUAL 8)
message("WA For LLVM8 : Igonre warning 4199 - Need to fix it")
  igc_config_flag_apply_settings(
      LinkerOptions
      CMAKE_SHARED_LINKER_FLAGS
      ALL_PATTERN ""
      SET_RAW
        "/MANIFEST:NO"
        "/ignore:4099"
        "/ignore:4197"
        "/ignore:4199"
      )
else()
  igc_config_flag_apply_settings(
      LinkerOptions
      CMAKE_SHARED_LINKER_FLAGS
      ALL_PATTERN ""
      SET_RAW
        "/MANIFEST:NO"
        "/ignore:4099"
        "/ignore:4197"
      )
endif()
  # Disable LTCG due to release build time increase
  #igc_config_flag_apply_settings(
  #    LinkerOptions
  #    CMAKE_STATIC_LINKER_FLAGS
  #    PATTERN "${IGC_BUILD__RELEASE_PATTERN}"
  #    SET
  #      LinkTimeCodeGeneration
  #)
# Force static linking of common libraries on Android for shared objects.
elseif(_igc_compiler_is_gnu_or_clang)
  if(NOT ANDROID AND NOT IGC_BUILD_DISABLE_FLAGS_GNU_CLANG)
    igc_config_flag_apply_settings(
        LinkerOptions
        CMAKE_SHARED_LINKER_FLAGS
        ALL_PATTERN ""
        SET_RAW
         -Wl,-z,noexecstack
         -Wl,-z,relro
         -Wl,-z,now
      )
  endif()
endif()

if(_igc_compiler_is_clang)
  igc_config_flag_apply_settings(
      LinkerOptions
      CMAKE_SHARED_LINKER_FLAGS
      ALL_PATTERN ""
      SET_RAW
        -shared
        -Wl,-undefined,dynamic_lookup
        -Wl,-headerpad_max_install_names
    )
endif()


# ================================== Compiler preprocessor definitions =================================

# ?  CL_NUMBER                < env:CL_NUMBER if env:CL_NUMBER != ''
# ?* BUILD_NUMBER             < env:BUILD_NUMBER if env:BUILD_NUMBER != ''
# M  IGC_EXPORTS=1            if !IGCStandalone
# M  _COMPILER_DLL_           if Compiler|| GenISAIntrinisics
# *  _CONSOLE                 if visa
# +  _CRT_SECURE_NO_WARNINGS
# +  _DEBUG                   if cfg:Debug
# +  _IGC_
# *  _LIB                     if build:static library
# +  _SCL_SECURE_NO_WARNINGS
# +* DEBUG                    if cfg:Debug
# +  DLL_MODE                 if visa
# M  GHAL3D_SHADERDUMP_ENABLE if IGCStandalone
# +  GHAL3D=USC
# +  ICBE_LHDM                if platform:Windows
# +* INSIDE_PLUGIN
# M  iSTD=USC_iSTD            if IGCStanalone
# +  ISTDLIB_UMD              ?
# +  NDEBUG                   if !cfg:Debug
# +  NOMINMAX
# M* RIIGC                    if IGCStanalone
# +  USC_DXX                  if cfg:Debug
# +  USC_EXPORTS
# +  VER_H                    if !platform:Windows
# M  WIN32                    if platform:Windows && bits:32
# +  WIN64                    if platform:Windows && bits:64
# +  i386=1                   if bits:32
# +  _X86_=1                  if bits:32
# +  _AMD64_                  if bits:64
# + ENABLE_REGISTRY_READ      if cfg:Debug

add_compile_definitions(
    _IGC_
    GHAL3D=USC
    _HAS_EXCEPTIONS=0
    IGC_EXPORTS=1
    USC_EXPORTS=1
    ISTDLIB_UMD
    IGC_CMAKE
    __STDC_CONSTANT_MACROS
    __STDC_LIMIT_MACROS
    _SCL_SECURE_NO_WARNINGS
    _CRT_SECURE_NO_WARNINGS
    NOMINMAX
    STD_CALL
    INSIDE_PLUGIN
    _COMPILER_DLL_
    $<$<CONFIG:Debug>:_DEBUG>
    $<$<CONFIG:Debug>:ENABLE_REGISTRY_READ>
    $<$<CONFIG:Debug>:USC_DXX>
    $<$<CONFIG:Release>:NDEBUG>
    $<$<EQUAL:${CMAKE_SIZEOF_VOID_P},4>:_X86_=1>
    $<$<EQUAL:${CMAKE_SIZEOF_VOID_P},4>:i386=1>
    $<$<EQUAL:${CMAKE_SIZEOF_VOID_P},8>:_AMD64_>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:ICBE_LINUX>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:LINUX>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:USE_MMX>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:USE_SSE>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:USE_SSE2>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:USE_SSE3>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:USE_SSSE3>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>:ICBE_LHDM>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>:_WIN32>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>:"WIN32">
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>:WIN32_LEAN_AND_MEAN=1>
    $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>:WINNT=1>
    $<$<AND:$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>,$<EQUAL:${CMAKE_SIZEOF_VOID_P},8>>:_WIN64>
    $<$<AND:$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>,$<EQUAL:${CMAKE_SIZEOF_VOID_P},8>>:WIN64>
    )

if(DEFINED VME_TYPES_DEFINED)
add_compile_definitions(
      VME_TYPES_DEFINED=${VME_TYPES_DEFINED}
    )
endif()

#SPIRV consumption flag
if(IGC_BUILD__SPIRV_ENABLED)
  add_compile_definitions(
      IGC_SPIRV_ENABLED
    )
endif()

#VC OPT switch on/off
if(IGC_BUILD__VC_ENABLED)
  add_compile_definitions(
      IGC_VC_ENABLED
    )
endif()

# Additional definitions for vISA projects.
set(IGC_BUID__VISA_COMPILE_DEFINITIONS
    DLL_MODE
  )

if(NOT ANDROID)
  add_compile_definitions(CL_KHR_FP64_EXT)
endif()

if(DEFINED ENV{TEST_P4_CHANGELIST})
  add_compile_definitions(
    TB_BUILD_ID=$ENV{TEST_P4_CHANGELIST}
  )
endif()

# ======================================================================================================

if(IGC_BUILD__SHOW_CFLAGS)
  get_cmake_property(_compilerOptionsVarNames VARIABLES)
  foreach(_compilerOptionsVarName ${_compilerOptionsVarNames})
    if(_compilerOptionsVarName MATCHES "^CMAKE_.*_FLAGS(_.*)?$")
      message("[F] ${_compilerOptionsVarName}:    ${${_compilerOptionsVarName}}")
    endif()
  endforeach()
endif()

# ==================================== LLVM package ====================================================

include("${CMAKE_CURRENT_SOURCE_DIR}/../external/llvm/llvm_deps.cmake")
include(igc_llvm)

# ==================================== LLD package ====================================================

if(IGC_OPTION__LLVM_LLD)
  include(igc_find_liblldELF)
endif()

# ==================================== WrapperLLVM package =============================================

add_subdirectory(WrapperLLVM)
igc_sg_define(IGC__WrapperLLVM)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/WrapperLLVM/include")

# ==================================== SPIRV-LLVM-Translator package ===================================

if(IGC_OPTION__LINK_KHRONOS_SPIRV_TRANSLATOR)
  include(igc_spirv)
endif()

# ======================================== Include directories =========================================

include_directories(
    "${IGC_CODEGEN_DIR}"

    "${IGC_BUILD__IGC_SRC_DIR}"
    "${IGC_BUILD__IGC_COMMON_DIR}"

    "${IGC_BUILD__GFX_DEV_SRC_DIR}"

    "${IGC_BUILD__COMMON_DIR}"
    "${IGC_BUILD__3D_COMMON_DIR}"

    "${IGC_BUILD__INC_DIR}"
    "${IGC_BUILD__INC_DIR}/common"

    "${IGC_BUILD__COMMON_COMPILER_DIR}"
    "${IGC_BUILD__COMMON_COMPILER_DIR}/API"

    "${IGC_BUILD__VISA_DIR}/include"

    "${IGC_OPTION__OUTPUT_DIR}"

    "${IGC_BUILD__IGC_BIN_DIR}/${IGC_CMAKE_CFG_INTDIR}"

    "${IGC_BUILD__IGC_SRC_DIR}/AdaptorOCL/ocl_igc_shared/executable_format"
    "${IGC_BUILD__IGC_SRC_DIR}/AdaptorOCL"
    )


include_directories(
  "${IGC_BUILD__COMMON_COMPILER_DIR}/common"
)
include_directories(
  "${CIF_INCLUDE_DIR}"
)

if(LLVM_ON_WIN32)
  include_directories(
      "${IGC_BUILD__COMMON_COMPILER_DIR}/adapters/d3d9/api"
      "${IGC_BUILD__COMMON_COMPILER_DIR}/adapters/d3d9"
      "${IGC_BUILD__COMMON_COMPILER_DIR}/adapters/d3d10/API"
    )
endif()

# ==================================== ZE Binary Writer ================================================

add_subdirectory(ZEBinWriter/zebin)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/ZEBinWriter/zebin/source")
set(ZEBIN_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/ZEBinWriter/zebin/source/autogen")
include_directories("${ZEBIN_INCLUDE_PATH}")

# ===================================== Projects and source groups =====================================

# Suffixes of main projects.
# __igc_common - contains sources/headers/resources/settings common for all main projects (see list below).
# __igc_dll    - dynamic library for IGC.
# __igc_lib    - static library for IGC.
# Static libraries are only used for some tools.
# NOTE: Due to limitation of Windows resources and exports cannot be passed
#       easily from static library to dynamic. For resources, please use


set(IGC_BUILD__MAIN_IGC_LIB_SUFFIXES
    "__igc_dll"
)

set(IGC_BUILD__PROJ__igc_dll              "${IGC_BUILD__PROJ_NAME_PREFIX}igc_dll")
set(IGC_BUILD__PROJ_LABEL__igc_dll        "${IGC_BUILD__PROJ__igc_dll}")

#FCL
set(IGC_BUILD__PROJ__fcl_dll              "${IGC_BUILD__PROJ_NAME_PREFIX}fcl_dll")
set(IGC_BUILD__PROJ_LABEL__fcl_dll        "${IGC_BUILD__PROJ__fcl_dll}")

set(IGC_BUILD__PROJ__igc_lib              "${IGC_BUILD__PROJ_NAME_PREFIX}igc_lib")
set(IGC_BUILD__PROJ_LABEL__igc_lib        "${IGC_BUILD__PROJ__igc_lib}")

set(IGC_BUILD__PROJ_LABEL__GenX_IR        "${IGC_BUILD__PROJ_NAME_PREFIX}vISA")

add_subdirectory(common)
igc_sg_define(IGC__common)
igc_sg_define(IGC__Common_CLElfLib)


if(CMAKE_SYSTEM_NAME MATCHES "Windows")
    set(IGC_BUILD__SPIRV_TOOLS_ENABLED ON)
endif()

if(IGC_BUILD__SPIRV_TOOLS_ENABLED)
    add_subdirectory("${IGC_SOURCE_DIR}/../external/SPIRV-Tools" "${IGC_OPTION__OUTPUT_DIR}/external/SPIRV-Tools/config" EXCLUDE_FROM_ALL)
    include_directories("${IGC_BUILD__SPIRV-Headers_DIR}/include")
    include_directories("${IGC_BUILD__SPIRV-Tools_DIR}/include")
    add_compile_definitions("$<$<CONFIG:Debug>:IGC_SPIRV_TOOLS_ENABLED>")
    igc_sg_define(IGC__SPIRV-Tools)
endif()

add_subdirectory(GenISAIntrinsics)

add_subdirectory(Options)

if(LLVM_ON_WIN32)
  add_subdirectory(AdaptorOCL)
  igc_sg_define(IGC__AdaptorOCL)

endif()



include(igc_find_opencl_clang)

if(IGC_BUILD__VC_ENABLED)
  add_subdirectory(CMFE)
endif()

if(IGC_BUILD__VC_ENABLED)
  add_subdirectory(VectorCompiler)
endif()

add_subdirectory(Compiler)
add_subdirectory(DebugInfo)
add_subdirectory(DriverInterface)
igc_sg_define(IGC__DriverInterface)

# Built-in Functions (and resources).
if(IGC_OPTION__BIF_LINK_BC)
  add_subdirectory(BiFModule)
  add_subdirectory(ElfPackager)
endif()

add_subdirectory(OCLFE)

if(MSVC)
  set(IGC_BUILD__RES__IGC__igc_common
      "${CMAKE_CURRENT_SOURCE_DIR}/igc.rc"
    )
  igc_rc_register_resource(IGC__igc_dll RESOURCES DriverInterface__igc_dll FILE "${IGC_BUILD__RES__IGC__igc_common}") # [WA#2]
  igc_rc_register_resource(IGC__igc_lib RESOURCES DriverInterface__igc_dll FILE "${IGC_BUILD__RES__IGC__igc_common}") # [WA#2]

  igc_rc_get_resource(IGC_BUILD__RES__IGC__igc_dll IGC__igc_dll)
  # Static libraries on Windows cannot pass resources to final libraries.
  set(IGC_BUILD__RES__IGC__igc_lib)
  source_group("Resources" FILES
    ${IGC_BUILD__RES__IGC__igc_dll}
  )
endif()


# Sources/headers for main libraries.
set(IGC_BUILD__SRC__IGC__igc_common
    ${IGC_BUILD__SRC__IGC_AdaptorOCL}
    ${IGC_BUILD__SRC__IGC_common}
    ${IGC_BUILD__SRC__IGC_Common_CLElfLib}
  )


set(IGC_BUILD__SRC__IGC__igc_dll
    ${IGC_BUILD__SRC__IGC__igc_common}
    ${IGC_BUILD__SRC__IGC_DriverInterface__igc_dll}
  )


#FCL
set(IGC_BUILD__SRC__IGC__fcl_dll
    ${IGC_BUILD__SRC__FCL}
  )

set(IGC_BUILD__SRC__IGC__igc_lib
    ${IGC_BUILD__SRC__IGC__igc_dll})

set(IGC_BUILD__HDR__IGC__igc_common
    ${IGC_BUILD__HDR__IGC_AdaptorOCL} # currently empty
    ${IGC_BUILD__HDR__IGC_common}
    ${IGC_BUILD__HDR__IGC_Common_CLElfLib}
    )

set(IGC_BUILD__HDR__IGC__igc_dll
    ${IGC_BUILD__HDR__IGC__igc_common}
    ${IGC_BUILD__HDR__IGC_DriverInterface__igc_dll}
    ${IGC_WrapperLLVM_HDR}
  )

#FCL
set(IGC_BUILD__HDR__IGC__fcl_dll
    ${IGC_BUILD__HDR__FCL}
  )

set(IGC_BUILD__HDR__IGC__igc_lib
    ${IGC_BUILD__HDR__IGC__igc_dll}
  )

#FCL
set(IGC_BUILD__RES__IGC__fcl_dll
    ${IGC_BUILD__RES__FCL}
  )

# Main library targets (library names).
add_library("${IGC_BUILD__PROJ__igc_dll}" SHARED
    ${IGC_BUILD__SRC__IGC__igc_dll}
    ${IGC_BUILD__HDR__IGC__igc_dll}
    ${IGC_BUILD__RES__IGC__igc_dll}
  )

#FCL
  add_library("${IGC_BUILD__PROJ__fcl_dll}" SHARED
    ${IGC_BUILD__SRC__IGC__fcl_dll}
    ${IGC_BUILD__HDR__IGC__fcl_dll}
    ${IGC_BUILD__RES__IGC__fcl_dll}
  )

add_dependencies("${IGC_BUILD__PROJ__fcl_dll}" opencl-clang-lib)

if(IGC_BUILD__LLVM_SOURCES AND IGC_OPTION__LLVM_LLD)
  if(UNIX)
    if(NOT ${CMAKE_BUILD_TYPE} EQUAL "Release")
      add_dependencies("${IGC_BUILD__PROJ__igc_dll}" lld)
    endif()
  else()
    add_dependencies("${IGC_BUILD__PROJ__igc_dll}" lld)
  endif()
endif()


target_include_directories(${IGC_BUILD__PROJ__igc_dll} INTERFACE
  "${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/ocl_igc_shared"
  "${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/ocl_igc_shared/device_enqueue"
  "${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/ocl_igc_shared/executable_format"
  "${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/cif"
  "${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/"
  "${IGC_BUILD__IGC_BIN_DIR}/AdaptorOCL/"
)


#IGC_DLL
igc_target_flag_property_add_once_config_var("${IGC_BUILD__PROJ__igc_dll}" LINK_FLAGS IGC_BUILD__EXPORT_SYMBOLS_LINK_FLAGS)
set_property(TARGET "${IGC_BUILD__PROJ__igc_dll}" PROPERTY PROJECT_LABEL "${IGC_BUILD__PROJ_LABEL__igc_dll}")

#FCL
#igc_target_flag_property_add_once_config_var("${IGC_BUILD__PROJ__fcl_dll}" LINK_FLAGS IGC_BUILD__EXPORT_SYMBOLS_LINK_FLAGS)
set_property(TARGET "${IGC_BUILD__PROJ__fcl_dll}" PROPERTY PROJECT_LABEL "${IGC_BUILD__PROJ_LABEL__fcl_dll}")


#Set Universal properties if this is universal build
if(MSVC AND IGC_OPTION__UNIVERSAL_DRIVER)
    bs_set_wdk(${IGC_BUILD__PROJ__igc_dll})
    set_target_properties(${IGC_BUILD__PROJ__igc_dll} PROPERTIES VS_PLATFORM_TOOLSET WindowsApplicationForDrivers10.0)
    set_target_properties(${IGC_BUILD__PROJ__igc_dll} PROPERTIES VS_GLOBAL_DriverTargetPlatform Universal)
    set_target_properties(${IGC_BUILD__PROJ__igc_dll} PROPERTIES VS_TARGET_PLATFORM_VERSION "")
    windows_libs_props_universal(${IGC_BUILD__PROJ__igc_dll})
    bs_set_wdk(${IGC_BUILD__PROJ__fcl_dll})
    set_target_properties(${IGC_BUILD__PROJ__fcl_dll} PROPERTIES VS_PLATFORM_TOOLSET WindowsApplicationForDrivers10.0)
    set_target_properties(${IGC_BUILD__PROJ__fcl_dll} PROPERTIES VS_GLOBAL_DriverTargetPlatform Universal)
    set_target_properties(${IGC_BUILD__PROJ__fcl_dll} PROPERTIES VS_TARGET_PLATFORM_VERSION "")
    windows_libs_props_universal(${IGC_BUILD__PROJ__fcl_dll})
endif()

if(IGC_OPTION__INCLUDE_IGC_COMPILER_TOOLS)
  # NOTE: Remember to always pass resources when linking with static library.
  #       Use igc_rc_get_resource() with resource identifier like IGC__igc_lib
  #       Also use IGC_BUILD__LINK_LINE__igc_lib variable to get target_link_libraries()'s line which
  #       links igc_lib correctly (with correct resolve of circular dependencies).
  add_library("${IGC_BUILD__PROJ__igc_lib}" STATIC
      ${IGC_BUILD__SRC__IGC__igc_lib}
      ${IGC_BUILD__HDR__IGC__igc_lib}
    )
  if(IGC_OPTION__LINK_KHRONOS_SPIRV_TRANSLATOR)
    target_link_libraries("${IGC_BUILD__PROJ__igc_lib}" PRIVATE LLVMSPIRVLib)
  endif()
  if(MSVC)
    bs_set_wdk(${IGC_BUILD__PROJ__igc_lib})
    windows_libs_props_universal(${IGC_BUILD__PROJ__igc_lib})
  endif()
  set_property(TARGET "${IGC_BUILD__PROJ__igc_lib}" PROPERTY PROJECT_LABEL "${IGC_BUILD__PROJ_LABEL__igc_lib}")
  set_property(TARGET "${IGC_BUILD__PROJ__igc_lib}" PROPERTY EXCLUDE_FROM_ALL YES)
  set(IGC_BUILD__MAIN_IGC_LIB_SUFFIXES
      ${IGC_BUILD__MAIN_IGC_LIB_SUFFIXES}
      "__igc_lib"
    )
endif()

# Output names.
if(LLVM_ON_UNIX)
  set(_cpuSuffix "")
else()

  igc_arch_get_cpu(_cpuSuffix)
endif()
set_target_properties("${IGC_BUILD__PROJ__igc_dll}" PROPERTIES OUTPUT_NAME "${IGC_LIBRARY_NAME}${_cpuSuffix}")
set_target_properties("${IGC_BUILD__PROJ__igc_dll}" PROPERTIES
                      VERSION "${IGC_API_MAJOR_VERSION}.${IGC_API_MINOR_VERSION}.${IGC_API_PATCH_VERSION}"
                      SOVERSION "${IGC_API_MAJOR_VERSION}")
unset(_cpuSuffix)

#FCL
if(LLVM_ON_UNIX)
  set(_cpuSuffix "")
else()
  igc_arch_get_cpu(_cpuSuffix)
endif()
set_target_properties("${IGC_BUILD__PROJ__fcl_dll}" PROPERTIES OUTPUT_NAME "${FCL_LIBRARY_NAME}${_cpuSuffix}")
set_target_properties("${IGC_BUILD__PROJ__fcl_dll}" PROPERTIES
                      VERSION "${IGC_API_MAJOR_VERSION}.${IGC_API_MINOR_VERSION}.${IGC_API_PATCH_VERSION}"
                      SOVERSION "${IGC_API_MAJOR_VERSION}")
unset(_cpuSuffix)

# Injecting external vISA project.
add_subdirectory("${IGC_BUILD__VISA_DIR}" visa)
set_property(TARGET "GenX_IR" APPEND PROPERTY COMPILE_DEFINITIONS
    ${IGC_BUID__VISA_COMPILE_DEFINITIONS}
  )
set_property(TARGET "GenX_IR" PROPERTY PROJECT_LABEL "${IGC_BUILD__PROJ_LABEL__GenX_IR}")


# =================================== Link targets and dependencies ====================================

foreach(_libBuildSuffix ${IGC_BUILD__MAIN_IGC_LIB_SUFFIXES})
  add_dependencies("${IGC_BUILD__PROJ${_libBuildSuffix}}"     "${IGC_BUILD__PROJ__GenISAIntrinsics}")
  add_dependencies("${IGC_BUILD__PROJ${_libBuildSuffix}}"     MDAutogen)

  if(MSVC AND IGC_OPTION__BIF_LINK_BC)
    add_dependencies("${IGC_BUILD__PROJ${_libBuildSuffix}}"   "${IGC_BUILD__PROJ__BiFModule_OCL}")
    add_dependencies("${IGC_BUILD__PROJ${_libBuildSuffix}}"   "${IGC_BUILD__PROJ__ElfPackager}")
  endif()
endforeach()

#FCL
add_dependencies("${IGC_BUILD__PROJ__fcl_dll}"     "${IGC_BUILD__PROJ__BiFModule_OCL}")
if (NOT CMAKE_WDDM_LINUX)
add_dependencies("${IGC_BUILD__PROJ__fcl_dll}"     "${IGC_BUILD__PROJ__ElfPackager}")
endif()

if(LLVM_ON_WIN32)
endif()


foreach(_libBuildSuffix ${IGC_BUILD__MAIN_IGC_LIB_SUFFIXES})
  get_property(_targetType TARGET "${IGC_BUILD__PROJ${_libBuildSuffix}}" PROPERTY TYPE)
  if(_targetType MATCHES "^STATIC_LIBRARY$")
    set(_targetIsStatic YES)
  else()
    set(_targetIsStatic NO)
  endif()
  unset(_targetType)

  # list of libraries linked in all configurations
  set(_targetLinkLineCommon)

  # Generated link line for IGC static library allows to properly use it in other projects.
  if(_targetIsStatic)
    list(APPEND _targetLinkLineCommon
        "${IGC_BUILD__PROJ${_libBuildSuffix}}"
      )
  endif()

  if(LLVM_ON_WIN32)
    list(APPEND _targetLinkLineCommon
        "${IGC_BUILD__PROJ__AdaptorOCL}"
    )
  endif()

list(APPEND _targetLinkLineCommon zebinlib)




  if(IGC_BUILD__SPIRV_TOOLS_ENABLED)
    list(APPEND _targetLinkLineCommon
        "$<$<CONFIG:Debug>:${IGC_BUILD__PROJ__SPIRV-Tools}>"
    )
  endif()


  list(APPEND _targetLinkLineCommon
      "${IGC_BUILD__PROJ__Compiler}"
      "${IGC_BUILD__PROJ__GenISAIntrinsics}"
      GenX_IR
      GenXDebugInfo
    )

  if(LLVM_ON_UNIX AND IGC_OPTION__BIF_LINK_BC)
    list(APPEND _targetLinkLineCommon
        "${IGC_BUILD__WHOLE_ARCHIVE}"
        "${IGC_BUILD__PROJ__BiFLib_OCL}"
        "${IGC_BUILD__NO_WHOLE_ARCHIVE}"
      )
  endif()

  # Generated link line for IGC static library allows to properly use it in other projects.
  if(_targetIsStatic)
    list(APPEND _targetLinkLineCommon
        "${IGC_BUILD__PROJ${_libBuildSuffix}}"
      )
  endif()

  if(IGC_BUILD__VC_ENABLED)
    list(APPEND _targetLinkLineCommon
      ${IGC_BUILD__PROJ_VC_LIBS_TO_LINK}
      )
    if(_targetIsStatic)
      # Add some VC headers for static library manually since there is
      # no private target_link_libraries for static igc library and
      # include directories are not propagated.
      target_link_libraries("${IGC_BUILD__PROJ${_libBuildSuffix}}"
          PRIVATE
            VCHeaders
        )
      get_target_property(VC_IGCDEPS_HEADERS VCIGCDeps INTERFACE_INCLUDE_DIRECTORIES)
      target_include_directories("${IGC_BUILD__PROJ${_libBuildSuffix}}"
          PRIVATE
            ${VC_IGCDEPS_HEADERS}
        )
    endif()
  endif()

  list(APPEND _targetLinkLineCommon
      "${IGC_BUILD__START_GROUP}"
      ${IGC_BUILD__LLVM_LIBS_TO_LINK}
      "${IGC_BUILD__END_GROUP}"
    )

  if(_targetIsStatic)
    # Link line for projects that use IGC as static library (allows to resolve multi-circular dependencies between libraries).
    set("IGC_BUILD__LINK_LINE_RELEASE${_libBuildSuffix}"
        ${_targetLinkLineCommon}
      )
  else()
    if(CMAKE_WDDM_LINUX)
    target_link_libraries("${IGC_BUILD__PROJ${_libBuildSuffix}}" PRIVATE
        pthread
        "${}"
        "${_targetLinkLineCommon}"
        "${CMAKE_DL_LIBS}"
      )
    else()
    target_link_libraries("${IGC_BUILD__PROJ${_libBuildSuffix}}" PRIVATE
        "${_targetLinkLineCommon}"
        "${CMAKE_DL_LIBS}"
      )
    endif()
    # Link line for shared / dynamic library requires only library project (all static libs are linked inside).
    set_property(TARGET "${IGC_BUILD__PROJ${_libBuildSuffix}}" PROPERTY LINK_INTERFACE_LIBRARIES "")
    set("IGC_BUILD__LINK_LINE${_libBuildSuffix}"
        "${IGC_BUILD__PROJ${_libBuildSuffix}}"
      )
  endif()
endforeach()

#FCL
  get_property(_targetType TARGET "${IGC_BUILD__PROJ__fcl_dll}" PROPERTY TYPE)
  if(_targetType MATCHES "^STATIC_LIBRARY$")
    set(_targetIsStatic YES)
  else()
    set(_targetIsStatic NO)
  endif()
  unset(_targetType)

  set(_targetLinkLine)

  # Generated link line for IGC/IGC RS static library allows to properly use it in other projects.
  if(_targetIsStatic)
    list(APPEND _targetLinkLine
        "${IGC_BUILD__PROJ${_libBuildSuffix}}"
      )
  endif()

  # Generated link line for IGC/IGC RS static library allows to properly use it in other projects.
  if(_targetIsStatic)
    list(APPEND _targetLinkLine
        "${IGC_BUILD__PROJ__fcl_dll}"
      )
  endif()

    if(LLVM_ON_UNIX)
      list(APPEND _targetLinkLine
          "${IGC_BUILD__WHOLE_ARCHIVE}"
          "${IGC_BUILD__PROJ__CTHLib_FCL}"
          "${IGC_BUILD__NO_WHOLE_ARCHIVE}"
        )
    endif()

  list(APPEND _targetLinkLine
      "${IGC_BUILD__START_GROUP}"
      ${IGC_BUILD__LLVM_LIBS_TO_LINK}
      "${IGC_BUILD__END_GROUP}"
    )

list(REMOVE_ITEM _targetLinkLine
    IGC_BUILD__LLVM_LIBS_TO_LINK
    )

if(_targetIsStatic)
    # Link line for projects that use IGC as static library (allows to resolve multi-circular dependencies between libraries).
    set("IGC_BUILD__LINK_LINE__fcl_dll"
        ${_targetLinkLine}
      )
  else()
    if (UNIX)
        set(COMMON_CLANG opencl-clang-lib)
    else()
        set(COMMON_CLANG "")
    endif()

    target_link_libraries("${IGC_BUILD__PROJ__fcl_dll}"
        ${_targetLinkLine}
        ${COMMON_CLANG}
        ${CMAKE_DL_LIBS}
      )
    if(IGC_BUILD__VC_ENABLED)
      target_link_libraries("${IGC_BUILD__PROJ__fcl_dll}" AdaptorCM)
    endif()
    # Link line for shared / dynamic library requires only library project (all static libs are linked inside).
    set_property(TARGET "${IGC_BUILD__PROJ__fcl_dll}" PROPERTY LINK_INTERFACE_LIBRARIES "")
    set("IGC_BUILD__LINK_LINE__fcl_dll"
        "${IGC_BUILD__PROJ__fcl_dll}"
      )
  endif()

unset(_targetIsStatic)
unset(_targetLinkLine)



if(IGC_OPTION__INCLUDE_IGC_COMPILER_TOOLS)
  if (IGC_OPTION__BUILD_IGC_OPT)
    add_subdirectory(igc_opt)
  endif()
  # TODO: If we want IGCStandalone on Linux, someone must clean the code, so it will be compiling.
  if(LLVM_ON_UNIX)
    add_subdirectory("${IGC_BUILD__TOOLS_IGC_DIR}" tools)
  endif()
  if(LLVM_ON_WIN32)
    add_subdirectory("${IGC_BUILD__TOOLS_IGC_DIR}" ist)
  endif()
endif()

if(MSVC)
  add_custom_command( TARGET ${IGC_BUILD__PROJ__igc_dll}
    POST_BUILD
    COMMAND "${CMAKE_COMMAND}" -E copy "$<TARGET_FILE:${IGC_BUILD__PROJ__igc_dll}>" "$<TARGET_FILE_DIR:${IGC_BUILD__PROJ__igc_opt}>"
    COMMAND "${CMAKE_COMMAND}" -E copy "$<TARGET_PDB_FILE:${IGC_BUILD__PROJ__igc_dll}>" "$<TARGET_FILE_DIR:${IGC_BUILD__PROJ__igc_opt}>"
    )
endif()

# ============================================== LIT TESTS =============================================

add_subdirectory(Compiler/tests)
if(TARGET "check-igc")
  add_dependencies("${IGC_BUILD__PROJ__igc_dll}" "check-igc")
endif()


# ======================================================================================================

# Workaround for MSVS10 to avoid the "Dialog Hell"
# NOTE: This could be removed with future version of CMake.
if(MSVC_VERSION EQUAL 1600)
  set(IGC_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/IGC.sln")
  if (EXISTS "${IGC_SLN_FILENAME}")
    file(APPEND "${IGC_SLN_FILENAME}" "\n# This should be regenerated!\n")
  endif (EXISTS "${IGC_SLN_FILENAME}")
endif()

########################################################################
# cpack to create deb package
########################################################################

set(IGC_PC_PACKAGE_RELEASE "")
if(DEFINED IGC_PACKAGE_RELEASE)
  set(IGC_PC_PACKAGE_RELEASE "-${IGC_PACKAGE_RELEASE}")
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/igc.opencl.h.in ${IGC_BUILD__IGC_BIN_DIR}/AdaptorOCL/igc.opencl.h)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/igc-opencl.pc.in ${IGC_BUILD__IGC_BIN_DIR}/AdaptorOCL/igc-opencl.pc @ONLY)

if(UNIX)
  install(TARGETS ${IGC_BUILD__PROJ__igc_dll} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT igc-core)
  install(TARGETS ${IGC_BUILD__PROJ__fcl_dll} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} COMPONENT igc-opencl)
  install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/ocl_igc_shared DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/igc COMPONENT igc-opencl-devel)
  install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/ocl_igc_interface DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/igc COMPONENT igc-opencl-devel)
  install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/AdaptorOCL/cif DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/igc COMPONENT igc-opencl-devel)

  if(IGC_BUILD__LLVM_SOURCES AND IGC_OPTION__LLVM_LLD)
    # For now lld could be included only via building from LLVM sources
    if(NOT ${CMAKE_BUILD_TYPE} EQUAL "Release")
      install(TARGETS lld RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} COMPONENT igc-opencl-devel)
    endif()
  endif()

  install(
    CODE "file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/tmp/postinst \"/sbin/ldconfig\n\" )"
    CODE "file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/tmp/postrm \"/sbin/ldconfig\n\" )"
    CODE "file( COPY ${CMAKE_CURRENT_BINARY_DIR}/tmp/postinst DESTINATION ${CMAKE_CURRENT_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE )"
    CODE "file( COPY ${CMAKE_CURRENT_BINARY_DIR}/tmp/postrm DESTINATION ${CMAKE_CURRENT_BINARY_DIR} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE )"
    COMPONENT igc-core
  )

  install(FILES ${IGC_BUILD__IGC_BIN_DIR}/AdaptorOCL/igc-opencl.pc DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig COMPONENT igc-opencl-devel)
  install(FILES ${IGC_BUILD__IGC_BIN_DIR}/AdaptorOCL/igc.opencl.h DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/igc COMPONENT igc-opencl-devel)
   if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../NOTICES.txt)
    install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../NOTICES.txt DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/igc COMPONENT igc-core)
  endif()
  install(FILES ${IGC_BUILD__VISA_DIR}/include/RelocationInfo.h DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/visa COMPONENT igc-opencl-devel)
  install(DIRECTORY ${IGC_BUILD__VISA_DIR}/iga/IGALibrary/api/ DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/iga COMPONENT igc-opencl-devel FILES_MATCHING PATTERN "*.h*")
elseif (WIN32)
  install(TARGETS ${IGC_BUILD__PROJ__igc_dll}
          RUNTIME DESTINATION Release/lh64          CONFIGURATIONS Release)
  install(TARGETS ${IGC_BUILD__PROJ__igc_dll}
          RUNTIME DESTINATION Debug/lh64            CONFIGURATIONS Debug)

  install(FILES $<TARGET_PDB_FILE:${IGC_BUILD__PROJ__igc_dll}>
          DESTINATION Release/lh64/pdb              CONFIGURATIONS Release)
  install(FILES $<TARGET_PDB_FILE:${IGC_BUILD__PROJ__igc_dll}>
          DESTINATION Debug/lh64/pdb                CONFIGURATIONS Debug)

  if(CMAKE_SIZEOF_VOID_P EQUAL 8) # Only copy 64 build

    if(IGC_BUILD__LLVM_SOURCES AND IGC_OPTION__LLVM_LLD)
      # For now lld could be included only via building from LLVM sources
      install(TARGETS lld RUNTIME
              DESTINATION ../Test_Tools/Release/x64/Standalones CONFIGURATIONS Release)
      install(TARGETS lld RUNTIME
              DESTINATION ../Test_Tools/Debug/x64/Standalones            CONFIGURATIONS Debug)
    endif()

    install(TARGETS ${IGC_BUILD__PROJ__igc_dll} RUNTIME
            DESTINATION ../Test_Tools/Release/x64/Standalones          CONFIGURATIONS Release)
    install(TARGETS ${IGC_BUILD__PROJ__igc_dll} RUNTIME
            DESTINATION ../Test_Tools/Debug/x64/Standalones            CONFIGURATIONS Debug)

    install(FILES $<TARGET_PDB_FILE:${IGC_BUILD__PROJ__igc_dll}>
            DESTINATION ../Test_Tools/Release/x64/Standalones          CONFIGURATIONS Release)
    install(FILES $<TARGET_PDB_FILE:${IGC_BUILD__PROJ__igc_dll}>
            DESTINATION ../Test_Tools/Debug/x64/Standalones            CONFIGURATIONS Debug)
  endif(CMAKE_SIZEOF_VOID_P EQUAL 8)

  install(TARGETS ${IGC_BUILD__PROJ__fcl_dll}
          RUNTIME DESTINATION Release/lh64          CONFIGURATIONS Release)
  install(TARGETS ${IGC_BUILD__PROJ__fcl_dll}
          RUNTIME DESTINATION Debug/lh64            CONFIGURATIONS Debug)

  install(FILES $<TARGET_PDB_FILE:${IGC_BUILD__PROJ__fcl_dll}>
          DESTINATION Release/lh64/pdb              CONFIGURATIONS Release)
  install(FILES $<TARGET_PDB_FILE:${IGC_BUILD__PROJ__fcl_dll}>
          DESTINATION Debug/lh64/pdb                CONFIGURATIONS Debug)
endif()

if(UNIX)
  if(IGC_OPTION__CPACK_GENERATOR)
    set(CPACK_GENERATOR "${IGC_OPTION__CPACK_GENERATOR}")
  else()
    # If generators list was not defined build native package for current distro
    if(EXISTS "/etc/debian_version")
      set(CPACK_GENERATOR "DEB")
    elseif(EXISTS "/etc/redhat-release")
      set(CPACK_GENERATOR "RPM")
    else()
      set(CPACK_GENERATOR "TXZ")
      set(CPACK_SET_DESTDIR ON)
    endif()
  endif()

  set(CPACK_DEBIAN_PACKAGE_MAINTAINER "intel")
  set(CPACK_PACKAGE_ARCHITECTURE "x86_64")
  set(CPACK_PACKAGE_NAME "intel")
  set(CPACK_PACKAGE_VERSION_MAJOR ${IGC_API_MAJOR_VERSION})
  set(CPACK_PACKAGE_VERSION_MINOR ${IGC_API_MINOR_VERSION})
  set(CPACK_PACKAGE_VERSION_PATCH ${IGC_API_PATCH_VERSION})
  set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
  set(CPACK_PACKAGE_INSTALL_DIRECTORY ${IGC_INSTALL_TIME_ROOT_DIR})
  set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "postinst;postrm")
  set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Intel(R) Graphics Compiler for OpenCL(TM)")
  set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
  set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
  set(CPACK_RPM_PACKAGE_RELOCATABLE TRUE)
  set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64")

  set(CPACK_DEBIAN_IGC-CORE_FILE_NAME "intel-igc-core_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
  set(CPACK_DEBIAN_IGC-MEDIA_FILE_NAME "intel-igc-media_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
  set(CPACK_DEBIAN_IGC-MEDIA_PACKAGE_DEPENDS "intel-igc-core(=${CPACK_PACKAGE_VERSION})")
  set(CPACK_DEBIAN_IGC-OPENCL_FILE_NAME "intel-igc-opencl_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
  set(CPACK_DEBIAN_IGC-OPENCL_PACKAGE_DEPENDS "intel-igc-core(=${CPACK_PACKAGE_VERSION})")
  set(CPACK_DEBIAN_IGC-OPENCL-DEVEL_FILE_NAME "intel-igc-opencl-devel_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
  set(CPACK_DEBIAN_IGC-OPENCL-DEVEL_PACKAGE_DEPENDS "intel-igc-opencl(=${CPACK_PACKAGE_VERSION})")

  set(CPACK_RPM_IGC-CORE_FILE_NAME "intel-igc-core-${CPACK_PACKAGE_VERSION}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm")
  set(CPACK_RPM_IGC-MEDIA_FILE_NAME "intel-igc-media-${CPACK_PACKAGE_VERSION}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm")
  set(CPACK_RPM_IGC-MEDIA_PACKAGE_REQUIRES "intel-igc-core = ${CPACK_PACKAGE_VERSION}")
  set(CPACK_RPM_IGC-OPENCL_FILE_NAME "intel-igc-opencl-${CPACK_PACKAGE_VERSION}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm")
  set(CPACK_RPM_IGC-OPENCL_PACKAGE_REQUIRES "intel-igc-core = ${CPACK_PACKAGE_VERSION}")
  set(CPACK_RPM_IGC-OPENCL-DEVEL_FILE_NAME "intel-igc-opencl-devel-${CPACK_PACKAGE_VERSION}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm")
  set(CPACK_RPM_IGC-OPENCL-DEVEL_PACKAGE_REQUIRES "intel-igc-opencl = ${CPACK_PACKAGE_VERSION}}")

  set(CPACK_ARCHIVE_IGC-CORE_FILE_NAME "intel-igc-core-${CPACK_PACKAGE_VERSION}.${CPACK_PACKAGE_ARCHITECTURE}")
  set(CPACK_ARCHIVE_IGC-MEDIA_FILE_NAME "intel-igc-media-${CPACK_PACKAGE_VERSION}.${CPACK_PACKAGE_ARCHITECTURE}")
  set(CPACK_ARCHIVE_IGC-OPENCL_FILE_NAME "intel-igc-opencl-${CPACK_PACKAGE_VERSION}.${CPACK_PACKAGE_ARCHITECTURE}")
  set(CPACK_ARCHIVE_IGC-OPENCL-DEVEL_FILE_NAME "intel-igc-opencl-devel-${CPACK_PACKAGE_VERSION}.${CPACK_PACKAGE_ARCHITECTURE}")

  set(CPACK_DEB_COMPONENT_INSTALL ON)
  set(CPACK_RPM_COMPONENT_INSTALL ON)
  set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
  set(CPACK_COMPONENTS_ALL igc-core igc-media igc-opencl igc-opencl-devel)

  include (CPack)
endif(UNIX)
