cmake_minimum_required (VERSION 3.1)

# Use new policy for 'install_name' and RPATH on macOS (use `cmake --help-policy CMP0068` for details)
cmake_policy(SET CMP0068 NEW)
# Use new policy for `FindOpenGL` to prefer GLVND by default when available on linux (use `cmake --help-policy CMP0072` for details).
cmake_policy(SET CMP0072 NEW)

# On Windows, if the user doesn't specify a value,
# 'CMAKE_BUILD_TYPE' is automatically initialized to 'Debug' after 'project()'.
# So we need to check this variable at this point.
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose the type of build, options are: Debug, Release, RelWithDebInfo or MinSizeRel")
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel")

if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
        AND NOT CMAKE_BUILD_TYPE STREQUAL "Release"
        AND NOT CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"
        AND NOT CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
    message(FATAL_ERROR "Invalid value for CMAKE_BUILD_TYPE: '${CMAKE_BUILD_TYPE}' (required Debug, Release, RelWithDebInfo or MinSizeRel)")
endif()

project (sight)

enable_testing()

include(CheckVariableExists)
include(CMakeParseArguments)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/build/macros.cmake)

########################################################################################################################
# User options
########################################################################################################################

option(BUILD_SDK "Build Sight as a SDK" OFF)

# Tests build / run options
set(BUILD_TESTS ON CACHE BOOL "Configures projects associated tests (<project>Test projects)")
set(TESTS_XML_OUTPUT OFF CACHE BOOL "Tests will generate an xml output, suitable for CI integration")
mark_as_advanced(TESTS_XML_OUTPUT)
set(TESTS_FILTER "" CACHE STRING "Allows to only build/run tests whose path contains the filter string.")
mark_as_advanced(TESTS_FILTER)

set(SET_API_VERSION ON)

option(ENABLE_PCH "Use pre-compiled headers to speedup the compilation" ON)
option(VERBOSE_PCH "Display debug messages to help debugging PCH" OFF)
mark_as_advanced(ENABLE_PCH)
mark_as_advanced(VERBOSE_PCH)

# QML_IMPORT_PATH allows qtCreator to find the qml modules created in our bundles
set(QML_IMPORT_PATH "" CACHE STRING "Path of the Qml modules." FORCE)
mark_as_advanced(QML_IMPORT_PATH)

include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/build/PrecompiledHeader.cmake)

if(MSVC)
    if(NOT DEFINED CMAKE_PCH_COMPILER_TARGETS)
        # this will be executed in just before makefile generation
        variable_watch(CMAKE_BACKWARDS_COMPATIBILITY pch_msvc_hook)
    endif()
endif()

if(CMAKE_CONFIGURATION_TYPES)
    set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE STRING "List of supported configurations." FORCE)
endif()

set(CREATE_SUBPROJECTS OFF CACHE BOOL "Create a project for each subproject")

set(PROJECTS_TO_BUILD CACHE STRING
        "List of projects that will be configured for build.
        Leave empty to configure all projects"
    )

# Use solution folders.
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER automoc)

set(SPYLOG_LEVEL "error" CACHE STRING "Log level")
set(SPYLOG_LEVEL_VALUES "fatal;error;warning;info;debug;trace" CACHE INTERNAL
    "List of possible values for log level")
set(SPYLOG_LEVEL_MAP_fatal 1)
set(SPYLOG_LEVEL_MAP_error 2)
set(SPYLOG_LEVEL_MAP_warning 3)
set(SPYLOG_LEVEL_MAP_info 4)
set(SPYLOG_LEVEL_MAP_debug 5)
set(SPYLOG_LEVEL_MAP_trace 6)
set_property(CACHE SPYLOG_LEVEL PROPERTY STRINGS ${SPYLOG_LEVEL_VALUES} )

########################################################################################################################
# Compile flags
########################################################################################################################
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Workarround to avoid compile error about OpenGL on macos >= 10.14
if(APPLE)
    add_definitions(-DGL_SILENCE_DEPRECATION)
endif()

if(MSVC AND ENABLE_PCH)
    # Store debug information in the .obj file instead of a PDB.
    string(REGEX REPLACE "/Z[iI]" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
    string(REGEX REPLACE "/Z[iI]" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
    # Force set debug compile flags.
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Debug flags" FORCE)
    set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "RelWithDebInfo flags" FORCE)
endif()

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")  #racy backward compatibility

# Set warning level and function export visibility on Unix
if(UNIX)
    if(APPLE)
        # actually the flag -fvisibility=hidden makes application crash on OSX
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion -Wno-unused-parameter -Wno-ignored-qualifiers -fvisibility-ms-compat")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -Wno-unused-parameter -Wno-ignored-qualifiers -fvisibility-ms-compat")
        set(CMAKE_MACOSX_RPATH ON)
    else()
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion -Wno-unused-parameter -Wno-ignored-qualifiers -fvisibility=hidden")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -Wno-unused-parameter -Wno-ignored-qualifiers -fvisibility=hidden")
    endif()
    # Color for ninja and Clang on Linux and OSX
    if (CMAKE_GENERATOR STREQUAL "Ninja")
        if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcolor-diagnostics")
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
        #Color output for gcc > 4.9
        elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.8.99")
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color")
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color")
        endif()
    endif()
elseif(MSVC)
    # Force to always compile with W4
    if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
        string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
    else()
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
    endif()
endif()

# Use external/system includes available from Visual Studio 15.6
# source https://gitlab.kitware.com/cmake/cmake/issues/17904
if (MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.14)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /experimental:external /external:W0 ")
    set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "/external:I ")
endif()

# Building with all your cores on Visual Studio IDE
if(MSVC_IDE)
    set(CMAKE_C_FLAG "${CMAKE_C_FLAGS} /MP")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
endif()

if(${WIN32} AND ${MSVC})
    if(${MSVC_VERSION} GREATER 1914)
        add_definitions(" -D_ENABLE_EXTENDED_ALIGNED_STORAGE")
    endif()
endif()

########################################################################################################################
# External libraries management
########################################################################################################################

if(UNIX AND NOT APPLE)
    option(USE_SYSTEM_LIB "Use system libraries to compile sight" OFF)
endif()

set(FWCMAKE_RESOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake/)

if(USE_SYSTEM_LIB)
    # Append our 'FindPackages.cmake' to CMAKE_MODULE_PATH and include BinPkgs config file
    list(APPEND CMAKE_PREFIX_PATH ${FWCMAKE_RESOURCE_PATH}/modules)
    list(APPEND CMAKE_MODULE_PATH ${FWCMAKE_RESOURCE_PATH}/modules)
    list(APPEND CMAKE_FIND_ROOT_PATH ${FWCMAKE_RESOURCE_PATH}/modules)

    # Parsing of 'fw-*.cmake' scripts. This should go away at some point if we use CMake properly
    file(GLOB LIB_CONFIGS ${FWCMAKE_RESOURCE_PATH}/modules/fw-*.cmake )
    foreach(LIB_CONFIG ${LIB_CONFIGS})
        message(STATUS "include: ${LIB_CONFIG}")
        include("${LIB_CONFIG}")
    endforeach()
else()
    option(CONAN_BUILD_MISSING "Build missing conan package automatically (experimental)" OFF)
    mark_as_advanced(CONAN_BUILD_MISSING)
    include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/conan/conan-deps.cmake)
    include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/conan/conan.cmake)
endif()

########################################################################################################################
# Automatic detection of additional repositories using .sight files
########################################################################################################################
file(GLOB ADDITIONAL_REPOSITORIES_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../*/.sight ${CMAKE_CURRENT_SOURCE_DIR}/../*/.fw4spl)

foreach(REPOSITORY ${ADDITIONAL_REPOSITORIES_FILES})
    file(READ ${REPOSITORY} REPO_RAW_NAME)
    string(STRIP ${REPO_RAW_NAME} REPO_RAW_NAME)
    string(TOUPPER ${REPO_RAW_NAME} REPO_NAME)

    if(NOT ${REPO_NAME} STREQUAL "SIGHT")

        get_filename_component(REPO_DIR ${REPOSITORY} DIRECTORY)
        get_filename_component(REPO_DIR ${REPO_DIR} ABSOLUTE)

        option(BUILD_${REPO_NAME} "Enable ${REPO_NAME} repository" ON)
        list(APPEND ADDITIONAL_REPOSITORIES_OPTION BUILD_${REPO_NAME})
        list(APPEND ADDITIONAL_REPOSITORIES_NAME ${REPO_RAW_NAME})
        list(APPEND ADDITIONAL_REPOSITORIES ${REPO_DIR})
    endif()
endforeach()

# parse additional CMakeLists
if(ADDITIONAL_REPOSITORIES)
    list(LENGTH ADDITIONAL_REPOSITORIES ADDITIONAL_REPOSITORIES_LEN)

    math(EXPR ADDITIONAL_REPOSITORIES_LEN ${ADDITIONAL_REPOSITORIES_LEN}-1)
    foreach(REPO_INDEX RANGE ${ADDITIONAL_REPOSITORIES_LEN})
        list(GET ADDITIONAL_REPOSITORIES ${REPO_INDEX} ADDITIONAL_REPO)
        list(GET ADDITIONAL_REPOSITORIES_OPTION ${REPO_INDEX} ADDITIONAL_REPO_OPTION)

        if(EXISTS ${ADDITIONAL_REPO}/CMakeLists.txt AND ${ADDITIONAL_REPO_OPTION})
            get_filename_component(DIR_NAME ${ADDITIONAL_REPO} NAME)
            add_subdirectory(${ADDITIONAL_REPO} ${DIR_NAME})
        endif()
    endforeach()
endif()

########################################################################################################################
# Default paths settings for libraries, bundles and resources
########################################################################################################################

if(WIN32)
    set(FW_INSTALL_PATH_SUFFIX )
    set(FWBUNDLE_LIB_PREFIX "${CMAKE_INSTALL_BINDIR}")
    set(FWBUNDLE_RC_PREFIX "${CMAKE_INSTALL_DATADIR}")
else()
    set(FW_INSTALL_PATH_SUFFIX "sight")
    set(FWBUNDLE_LIB_PREFIX "${CMAKE_INSTALL_LIBDIR}/${FW_INSTALL_PATH_SUFFIX}")
    set(FWBUNDLE_RC_PREFIX "${CMAKE_INSTALL_DATADIR}/${FW_INSTALL_PATH_SUFFIX}")
endif()

set(LIBRARY_OUTPUT_DIR lib/${FW_INSTALL_PATH_SUFFIX})

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${LIBRARY_OUTPUT_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${LIBRARY_OUTPUT_DIR})
# Fixed path for multi-config builds (e.g. msvc)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
    string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
    set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin )
    set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${LIBRARY_OUTPUT_DIR} )
    set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${LIBRARY_OUTPUT_DIR} )
endforeach()

########################################################################################################################
# The Properties.cmake files are the entry point to scan for targets
# We really start the configure process here
########################################################################################################################
file(GLOB_RECURSE PROJECTS_PROPERTIES */Properties.cmake)

# Do the same in additional repositories
if(ADDITIONAL_REPOSITORIES)

    list(LENGTH ADDITIONAL_REPOSITORIES ADDITIONAL_REPOSITORIES_LEN)
    math(EXPR ADDITIONAL_REPOSITORIES_LEN ${ADDITIONAL_REPOSITORIES_LEN}-1)

    foreach(REPO_INDEX RANGE -${ADDITIONAL_REPOSITORIES_LEN} - 1)
        list(GET ADDITIONAL_REPOSITORIES ${REPO_INDEX} ADDITIONAL_REPO)
        list(GET ADDITIONAL_REPOSITORIES_OPTION ${REPO_INDEX} ADDITIONAL_REPO_OPTION)

        if(${ADDITIONAL_REPO_OPTION})
            list(GET ADDITIONAL_REPOSITORIES_NAME ${REPO_INDEX} ADDITIONAL_REPO_NAME)
            message(STATUS "Configuring additional repository " ${ADDITIONAL_REPO_NAME} " found in: " ${ADDITIONAL_REPO})
            file(GLOB_RECURSE ADDITIONAL_REPOSITORIES_PROPERTIES ${ADDITIONAL_REPO}/*/Properties.cmake)
            list(APPEND PROJECTS_PROPERTIES ${ADDITIONAL_REPOSITORIES_PROPERTIES})
            set(ADDITIONAL_REPOSITORIES_SOURCE_DIR "${ADDITIONAL_REPOSITORIES_SOURCE_DIR} ${ADDITIONAL_REPO}")
        endif()
    endforeach()
endif()

set(FWCONFIG_PACKAGE_LOCATION lib/cmake/sight)

unset(PROJECT_LIST)

# Parse all Properties.cmake files and populate a list of CMake variables for each projet
# to know its dependencies, requirements, version, pch usage, etc...
foreach(PROPERTIES_FILE ${PROJECTS_PROPERTIES})
    get_filename_component(PROJECT_DIR ${PROPERTIES_FILE} PATH)

    loadProperties("${PROPERTIES_FILE}")
    if(NOT NAME)
        message(FATAL_ERROR "${PROPERTIES_FILE}: Project NAME can not be empty.")
    endif()

    list(FIND DEPENDENCIES ${NAME} DEP_LOOP)
    if(DEP_LOOP GREATER -1)
        message(FATAL_ERROR "${PROPERTIES_FILE}: A project can not be its own dependency.")
    endif()

    list(FIND REQUIREMENTS ${NAME} REQ_LOOP)
    if(REQ_LOOP GREATER -1)
        message(FATAL_ERROR "${PROPERTIES_FILE}: A project can not be its own requirement.")
    endif()

    if(${NAME}_DIR)
        message(FATAL_ERROR "${PROPERTIES_FILE}: A project NAME must be unique in the workspace. ${NAME} already defined there : ${${NAME}_DIR}")
    endif()

    string( TOUPPER "${TYPE}" TYPE )

    set(${NAME}_DEPENDENCIES      "${DEPENDENCIES}")
    set(${NAME}_REQUIREMENTS      "${REQUIREMENTS}")
    set(${NAME}_DISABLE_PCH       "${DISABLE_PCH}")
    set(${NAME}_CONAN_DEPS        "${CONAN_DEPS}")
    set(${NAME}_WARNINGS_AS_ERRORS "${WARNINGS_AS_ERRORS}")

    # Get the pch target, test the existence of type variable to exclude unbuilt projects
    if(ENABLE_PCH AND TYPE AND NOT ${NAME}_DISABLE_PCH)
        set(${NAME}_PROJECT_DIR "${PROJECT_DIR}")

        getPchTarget(${NAME} ${PROJECT_DIR} ${TYPE} ${USE_PCH_FROM_TARGET})

        # Append the pch target as a dependency (duplicate will be stripped later if it was already a dependency)
        if(NOT ${${NAME}_PCH_TARGET} STREQUAL ${NAME})
            list(APPEND ${NAME}_REQUIREMENTS ${${NAME}_PCH_TARGET})
        endif()
    endif()

    set(${NAME}_VERSION "${VERSION}")
    set(${NAME}_DIR "${PROJECT_DIR}")

    if(TYPE STREQUAL "APP")
        set(${NAME}_UNIQUE "${UNIQUE}")
    endif()

    if( TYPE STREQUAL "BUNDLE" OR TYPE STREQUAL "APP" AND START)
        set(${NAME}_START "${START}")
    endif()

    set(${NAME}_START_BEFORE "${START_BEFORE}")

    list(APPEND PROJECT_LIST ${NAME})

endforeach()

# Now find all dependencies if we restrict the build to some projects
if(PROJECTS_TO_BUILD)
    set(PROJECT_LIST ${PROJECTS_TO_BUILD})
    findAllDependencies("${PROJECT_LIST}" PROJECT_LIST)

    set(REPOSITORIES_DIRECTORIES ${ADDITIONAL_REPOSITORIES})
    list(APPEND REPOSITORIES_DIRECTORIES ${CMAKE_SOURCE_DIR})

    foreach(PROJECT ${PROJECT_LIST})
        set(${PROJECT}_INSTALL 1)

        # Configure cpack to package the project sources.
        findProjectSubdirectory("${${PROJECT}_DIR}" "${REPOSITORIES_DIRECTORIES}" SOURCE_INSTALL_DIR)
        # Add the project to CPack's list of source directories.
        list(APPEND CPACK_SOURCE_INSTALLED_DIRECTORIES ${${PROJECT}_DIR} ${SOURCE_INSTALL_DIR})
    endforeach()

    # Copy important sight files in a temporary directory to be packaged when generating a source archive.
    set(PACKAGE_SRC_DIR "${CMAKE_BINARY_DIR}/package_source")
    file(MAKE_DIRECTORY ${PACKAGE_SRC_DIR})
    file(COPY CMakeLists.txt COPYING COPYING.LESSER README.md DESTINATION ${PACKAGE_SRC_DIR})
    list(APPEND CPACK_SOURCE_INSTALLED_DIRECTORIES ${PACKAGE_SRC_DIR} "." "${CMAKE_SOURCE_DIR}/CMake" "./CMake")

    message(STATUS "Project configuration is restricted to : ${PROJECTS_TO_BUILD}")
elseif(BUILD_SDK)
    foreach(PROJECT ${PROJECT_LIST})
        set(${PROJECT}_INSTALL 1)
    endforeach()
endif()

# Clear all previous tests from project list
findTests("${PROJECT_LIST}" "" PROJECT_TESTS)
if(PROJECT_TESTS)
    list(REMOVE_ITEM PROJECT_LIST ${PROJECT_TESTS})
endif()

findTests("${PROJECT_LIST}" "${TESTS_FILTER}" PROJECT_TESTS)
findAllDependencies("${PROJECT_TESTS}" PROJECT_TESTS_DEPS)
list(REMOVE_DUPLICATES PROJECT_TESTS_DEPS)

# Add all test sources to the source package. Needed to make the package buildable without setting BUILD_TESTS=OFF.
foreach(PROJECT ${PROJECT_TESTS_DEPS})
    findProjectSubdirectory("${${PROJECT}_DIR}" "${REPOSITORIES_DIRECTORIES}" SOURCE_INSTALL_DIR)
    list(APPEND CPACK_SOURCE_INSTALLED_DIRECTORIES ${${PROJECT}_DIR} ${SOURCE_INSTALL_DIR})
endforeach()

# Append tests to the project list
if(BUILD_TESTS)
    list(APPEND PROJECT_LIST ${PROJECT_TESTS_DEPS})
    list(REMOVE_DUPLICATES PROJECT_LIST)
endif()

# Find and install Conan packages
if(NOT USE_SYSTEM_LIB)
    findConanDeps("${PROJECT_LIST}" CONAN_DEPS_LIST)
    installConanDeps("${CONAN_DEPS_LIST}")
    add_definitions(${CONAN_DEFINES})

    # Import the shared C flags, we use python for that
    find_package(PythonInterp 3 QUIET)
    if(PYTHONINTERP_FOUND)
        # Set PYTHONPATH environment to be able to import common
        set(OLD_PYTHONPATH $ENV{PYTHONPATH})
        set(ENV{PYTHONPATH} ${CONAN_COMMON_ROOT})

        # Execute common.get_c_flags() and store it to ${SIGHT_C_FLAGS}
        execute_process(
            COMMAND ${PYTHON_EXECUTABLE} -u -c "import common; print(\"{0}\".format(common.get_c_flags()), sep='', end='', flush=True)"
            OUTPUT_VARIABLE SIGHT_C_FLAGS
        )
        string(STRIP ${SIGHT_C_FLAGS} SIGHT_C_FLAGS)

        # Execute common.get_cxx_flags() and store it to ${SIGHT_CXX_FLAGS}
        execute_process(
            COMMAND ${PYTHON_EXECUTABLE} -u -c "import common; print(\"{0}\".format(common.get_cxx_flags()), sep='', end='', flush=True)"
            OUTPUT_VARIABLE SIGHT_CXX_FLAGS
        )
        string(STRIP ${SIGHT_CXX_FLAGS} SIGHT_CXX_FLAGS)

        # Restore old PYTHONPATH environment
        set(ENV{PYTHONPATH} ${OLD_PYTHONPATH})
        unset(OLD_PYTHONPATH)
    else()
        # Use default values. This is a failsafe path, the options and flags maybe outdated.
        if(WIN32)
            set(SIGHT_C_FLAGS "/favor:blend /fp:strict /Qfast_transcendentals /arch:AVX /MP /bigobj /EHsc")
            set(SIGHT_CXX_FLAGS "${SIGHT_C_FLAGS}")
        else()
            set(SIGHT_C_FLAGS "-march=x86-64 -mtune=generic -mfpmath=sse -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -maes -mpclmul -mf16c")
            set(SIGHT_CXX_FLAGS "${SIGHT_C_FLAGS}")
        endif()
    endif()

    # Assign the shared C flags to everything
    set(CMAKE_C_FLAGS "${SIGHT_C_FLAGS} ${CMAKE_C_FLAGS}")
    set(CMAKE_CXX_FLAGS "${SIGHT_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")

    unset(SIGHT_C_FLAGS)
    unset(SIGHT_CXX_FLAGS)
endif()

# Define the path 'FW_EXTERNAL_LIBRARIES_DIR' used to find external libraries required by our applications
setExternalLibrariesDir()

########################################################################################################################
# Second projects scan where we actually perform the add_subdirectory() for each project and its dependencies
########################################################################################################################

unset(APP_TO_BUILD)
foreach(PROJECT ${PROJECT_LIST})
    addProject(${PROJECT})
endforeach()

########################################################################################################################
# Export and install targets
########################################################################################################################

if(BUILD_SDK)
    # Create the SightConfig.cmake file
    set(FWCONFIG_FILE ${CMAKE_SOURCE_DIR}/CMake/build/SightConfig.cmake.in)

    configure_file(${FWCONFIG_FILE} "${CMAKE_BINARY_DIR}/cmake/SightConfig.cmake" @ONLY)

    # Create the SightConfigVersion file
    set(SIGHT_VERSION ${GIT_TAG})

    write_basic_package_version_file(
      "${CMAKE_BINARY_DIR}/cmake/SightConfigVersion.cmake"
      VERSION ${SIGHT_VERSION}
      COMPATIBILITY AnyNewerVersion
    )

    if(NOT USE_SYSTEM_LIB)
        file(APPEND "${CMAKE_BINARY_DIR}/cmake/SightRequirements.cmake"
             "set(CONAN_DEFINES ${CONAN_DEFINES})\n")
    endif()

    # Install the SightConfig.cmake and SightConfigVersion.cmake
    install(
      FILES
        "${CMAKE_BINARY_DIR}/cmake/SightConfig.cmake"
        "${CMAKE_BINARY_DIR}/cmake/SightConfigVersion.cmake"
        "${CMAKE_BINARY_DIR}/cmake/SightRequirements.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/build/macros.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/conan/conan.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/conan/conan-deps.cmake"
      DESTINATION
        ${FWCONFIG_PACKAGE_LOCATION}
      COMPONENT
        dev
    )

    # Install some files needed for the build
    install(
      FILES
        "${CMAKE_SOURCE_DIR}/CMake/build/configure_file.cmake"
        "${FWCMAKE_RESOURCE_PATH}/cppunit/cppunit_main.cpp"
        "${CMAKE_SOURCE_DIR}/CMake/build/config.hpp.in"
        "${CMAKE_SOURCE_DIR}/CMake/build/plugin_config.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/build/plugin_config_command.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/build/plugin.xml.in"
        "${CMAKE_SOURCE_DIR}/CMake/build/profile_config.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/build/profile.xml.in"
        "${CMAKE_SOURCE_DIR}/CMake/build/registerServices.cpp.in"
        "${CMAKE_SOURCE_DIR}/CMake/build/spyLogLevel.hpp.in"
      DESTINATION
        ${FWCONFIG_PACKAGE_LOCATION}/build
      COMPONENT
        dev
    )

    # Install some files needed for the install
    install(
      FILES
        "${CMAKE_SOURCE_DIR}/CMake/install/generic_install.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/install/helper.cmake"
        "${CMAKE_SOURCE_DIR}/CMake/install/get_git_rev.cmake"
      DESTINATION
        ${FWCONFIG_PACKAGE_LOCATION}/install
      COMPONENT
        dev
    )

    if(APPLE)
        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/osx_install.cmake"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install
          COMPONENT
            dev
        )
        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/macos/rc/app.icns"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install/macos/rc
          COMPONENT
            dev
        )
        install(
          FILES
          "${CMAKE_SOURCE_DIR}/CMake/install/macos/osx_install_name_tool.py"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install/macos/
          COMPONENT
            dev
        )
        install(
          FILES
          "${CMAKE_SOURCE_DIR}/CMake/build/linux/template.sh.in"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/build/linux
          COMPONENT
            dev
        )
    elseif(WIN32)
        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/win_install.cmake"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install
          COMPONENT
            dev
        )
        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/template.bat.in"
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/setpath.bat.in"
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/windows_fixup.cmake.in"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install/windows
          COMPONENT
            dev
        )
        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/NSIS/NSIS.InstallOptions.ini.in"
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/NSIS/NSIS.template.in"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install/windows/NSIS/
          COMPONENT
            dev
        )
        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/NSIS/rc/banner_nsis.bmp"
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/NSIS/rc/dialog_nsis.bmp"
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/NSIS/rc/app.ico"
            "${CMAKE_SOURCE_DIR}/CMake/install/windows/NSIS/rc/license.rtf"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install/windows/NSIS/rc/
          COMPONENT
            dev
        )
    elseif(UNIX)
        install(
          FILES
          "${CMAKE_SOURCE_DIR}/CMake/build/linux/template.sh.in"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/build/linux
          COMPONENT
            dev
        )
        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/linux_install.cmake"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install
          COMPONENT
            dev
        )

        install(
          FILES
            "${CMAKE_SOURCE_DIR}/CMake/install/linux/template.sh.in"
            "${CMAKE_SOURCE_DIR}/CMake/install/linux/linux_fixup.cmake.in"
          DESTINATION
            ${FWCONFIG_PACKAGE_LOCATION}/install/linux
          COMPONENT
            dev
        )
    endif()
endif()


########################################################################################################################
# Misc generators
########################################################################################################################

# Doxygen documentation
option(BUILD_DOCUMENTATION "Build the doxygen documentation" OFF)
if(BUILD_DOCUMENTATION)
    option(BUILD_DOCSET "Build a Dash/Zeal/XCode docset" OFF)
    include(${FWCMAKE_RESOURCE_PATH}doxygen/doxygen_generator.cmake)
    doxygenGenerator(${PROJECT_LIST})
    if(BUILD_DOCSET)
        docsetGenerator(${PROJECT_LIST})
    endif()
else()
    unset(BUILD_DOCSET CACHE)
endif()

# VS Code project
option(GENERATE_VSCODE_WS "Generate VS Code workspace" OFF)
if(GENERATE_VSCODE_WS)
    include(${FWCMAKE_RESOURCE_PATH}vscode/vscode_generator.cmake)
    vscodeGenerator(${PROJECT_LIST})
endif()

########################################################################################################################
# Packaging for the SDK
########################################################################################################################
if(BUILD_SDK)
    set(FWPROJECT_NAME sight)
    generic_install()
endif()
