
#
# This source file is part of appleseed.
# Visit https://appleseedhq.net/ for additional information and resources.
#
# This software is released under the MIT license.
#
# Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
# Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#


#--------------------------------------------------------------------------------------------------
# gcc or clang on Linux.
#--------------------------------------------------------------------------------------------------

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    set (platform "linux-gcc")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    set (platform "linux-clang")
endif ()


#--------------------------------------------------------------------------------------------------
# Compiler version.
#--------------------------------------------------------------------------------------------------

execute_process (
    COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
    OUTPUT_VARIABLE COMPILER_VERSION
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    message (STATUS "Using gcc ${COMPILER_VERSION} as the compiler")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    message (STATUS "Using clang ${COMPILER_VERSION} as the compiler")
endif ()


#--------------------------------------------------------------------------------------------------
# Preprocessor definitions.
#--------------------------------------------------------------------------------------------------


#--------------------------------------------------------------------------------------------------
# Compilation/Linking Flags.
#--------------------------------------------------------------------------------------------------

# Flags common to all configurations.
set (c_compiler_flags_common
    -Wall
    -Wno-switch                                         # don't complain about unhandled enumeration values in switch
    -Wno-unknown-pragmas
    -Wno-sign-compare
    -Wno-unused-function
    -Wno-strict-aliasing
    -fno-math-errno                                     # ignore errno when calling math functions
    -fPIC                                               # emit position-independent code
)
set (cxx_compiler_flags_common
    -Wno-reorder
)
set (cxx_compiler_flags_common
    ${cxx_compiler_flags_common}
)
if (is_x86)
    if (USE_SSE)
        set (c_compiler_flags_common
            ${c_compiler_flags_common}
            -msse2                                      # enable SSE instruction sets up to SSE 2
        )
    endif ()
    if (USE_F16C)
        set (c_compiler_flags_common
            ${c_compiler_flags_common}
            -mf16c                                      # enable F16C instructions
        )
    endif ()
    if (USE_SSE42)
        set (c_compiler_flags_common
            ${c_compiler_flags_common}
            -msse4.2                                    # enable SSE instruction sets up to SSE 4.2
        )
    endif ()
    if (USE_AVX)
        set (c_compiler_flags_common
            ${c_compiler_flags_common}
            -mavx                                       # enable AVX instruction set
        )
    endif ()
    if (USE_AVX2)
        set (c_compiler_flags_common
            ${c_compiler_flags_common}
            -mavx2                                      # enable AVX2 instruction set
            -mfma                                       # enable FMA instruction
            -ffp-contract=off                           # for now only explicit fmadd
        )
    endif ()
endif ()
if (WARNINGS_AS_ERRORS)
    if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR
        CMAKE_BUILD_TYPE STREQUAL "Release")
        set (c_compiler_flags_common
            ${c_compiler_flags_common}
            -Werror                                     # treat Warnings As Errors
        )
        set (exe_linker_flags_common
            -Werror                                     # treat Warnings As Errors
        )
        set (shared_lib_linker_flags_common
            -Werror                                     # treat Warnings As Errors
        )
    endif ()
endif ()
if (HIDE_SYMBOLS)
    set (c_compiler_flags_common
        ${c_compiler_flags_common}
        -fvisibility=hidden                             # Hide all non-exported symbols
    )
    set (cxx_compiler_flags_common
        ${cxx_compiler_flags_common}
        -fvisibility=hidden -fvisibility-inlines-hidden # Hide all non-exported symbols
    )
    set (exe_linker_flags_common
        ${exe_linker_flags_common}
        -fvisibility=hidden -fvisibility-inlines-hidden # Hide all non-exported symbols
    )
    set (shared_lib_linker_flags_common
        ${shared_lib_linker_flags_common}
        -fvisibility=hidden -fvisibility-inlines-hidden # Hide all non-exported symbols
    )
endif ()

# Release configuration.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    set (c_compiler_flags_release
        -O3                                             # optimization level
        -fgcse-las                                      # eliminates stores followed by a load to the same positions
        -fgcse-sm                                       # moves load/save instructions out of loops, if possible
    )
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    set (c_compiler_flags_release
        -O3                                             # optimization level
    )
endif ()

#--------------------------------------------------------------------------------------------------
# Libraries.
#--------------------------------------------------------------------------------------------------

macro (link_against_platform target)
    target_link_libraries (${target}
        -lpthread
        -lrt
    )
endmacro ()

macro (link_against_embree target)
    target_link_libraries (${target} ${EMBREE_LIBRARIES})
endmacro ()

macro (link_against_lz4 target)
    target_link_libraries (${target} ${LZ4_LIBRARY})
endmacro ()

macro (link_against_ocio target)
    target_link_libraries (${target} ${OPENCOLORIO_LIBRARIES})
endmacro ()

macro (link_against_oiio target)
    target_link_libraries (${target} ${OPENIMAGEIO_LIBRARIES})
endmacro ()

macro (link_against_openexr target)
    target_link_libraries (${target} Imath::Imath OpenEXR::OpenEXR OpenEXR::Iex OpenEXR::IlmThread)
endmacro ()

macro (link_against_osl target)
    target_link_libraries (${target} ${oslexec_LIBRARY} ${oslcomp_LIBRARY} ${oslquery_LIBRARY})
endmacro ()

macro (link_against_xercesc target)
    target_link_libraries (${target} ${XERCES_LIBRARIES})
endmacro ()

macro (link_against_zlib target)
    target_link_libraries (${target} ${ZLIB_LIBRARIES})
endmacro ()


#--------------------------------------------------------------------------------------------------
# Copy a target binary to the sandbox.
#--------------------------------------------------------------------------------------------------

macro (get_sandbox_bin_path path)
    set (${path} ${PROJECT_SOURCE_DIR}/sandbox/bin/${CMAKE_BUILD_TYPE})
endmacro ()

macro (get_sandbox_lib_path path)
    set (${path} ${PROJECT_SOURCE_DIR}/sandbox/lib/${CMAKE_BUILD_TYPE})
endmacro ()

macro (get_sandbox_py_path path)
    get_sandbox_lib_path (${path})
    set (${path} ${${path}}/python)
endmacro ()

macro (get_relative_path_from_module_name path name)
    string (REPLACE "." "/" ${path} ${name})
endmacro ()

macro (add_copy_target_exe_to_sandbox_command target)
    get_target_property (target_path ${target} LOCATION)
    get_sandbox_bin_path (bin_path)

    add_custom_command (TARGET ${target} POST_BUILD
        COMMAND mkdir -p ${bin_path}
        COMMAND cp ${target_path} ${bin_path}
    )
endmacro ()

macro (add_copy_target_lib_to_sandbox_command target)
    get_target_property (target_path ${target} LOCATION)
    get_sandbox_lib_path (lib_path)

    add_custom_command (TARGET ${target} POST_BUILD
        COMMAND mkdir -p ${lib_path}
        COMMAND cp ${target_path} ${lib_path}
    )
endmacro ()

macro (add_copy_target_to_sandbox_py_module_command target module_name)
    get_target_property (target_path ${target} LOCATION)
    get_sandbox_py_path (py_path)
    get_relative_path_from_module_name (relative_module_path ${module_name})
    set (module_path "${py_path}/${relative_module_path}")

    add_custom_command (TARGET ${target} POST_BUILD
        COMMAND mkdir -p ${module_path}
        COMMAND cp ${target_path} ${module_path}
    )
endmacro ()

macro (add_copy_py_file_to_sandbox_py_module_command py_src module_name)
    get_sandbox_py_path (py_path)
    get_relative_path_from_module_name (relative_module_path ${module_name})
    set (module_path "${py_path}/${relative_module_path}")

    add_custom_command (TARGET appleseed.python.copy_py_files POST_BUILD
        COMMAND mkdir -p ${module_path}
        COMMAND cp ${py_src} ${module_path}
    )
endmacro ()

macro (add_copy_dir_to_sandbox_py_module_command py_dir module_name)
    get_sandbox_py_path (py_path)
    get_relative_path_from_module_name (relative_module_path ${module_name})
    set (module_path "${py_path}/${relative_module_path}")

    add_custom_command (TARGET appleseed.python.copy_py_files POST_BUILD
        COMMAND mkdir -p ${module_path}
        COMMAND cp -r ${py_dir} ${module_path}
    )
endmacro ()

macro (add_copy_studio_py_file_to_sandbox_py_module_command py_src module_name)
    get_sandbox_py_path (py_path)
    get_relative_path_from_module_name (relative_module_path ${module_name})
    set (module_path "${py_path}/${relative_module_path}")

    add_custom_command (TARGET appleseed.studio.copy_py_files POST_BUILD
        COMMAND mkdir -p ${module_path}
        COMMAND cp ${py_src} ${module_path}
    )
endmacro ()
