# Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
#
# This source file is part of the Cangjie project, licensed under Apache-2.0
# with Runtime Library Exception.
#
# See https://cangjie-lang.cn/pages/LICENSE for license information.

# The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.

# Find OpenSSL package and prepare OpenSSL link options if target platform supports. Cangjie project
# requires OpenSSL 1.1 or later version. This file will find OpenSSL package and check its satisifies
# our version requirement. The only exception here is OHOS. For OHOS, OpenSSL library has special
# library names which differ from the official built one. Therefore, OpenSSL library for OHOS is
# manually linked, which means that they don't have any configure checking and linkage errors (if there
# are any) will occur at build time.
# 
# Usage:
#
# include(PrepareOpenSSL)
#
# If this file is processed successfully, the following variable will be defined:
# - OPENSSL_CRYPTO_LINK_OPTIONS
# - OPENSSL_SSL_LINK_OPTIONS
#
# Other variables may not have values even this file has been processed successfully. Use with care.

if(OHOS)
    set(OPENSSL_CRYPTO_LINK_OPTIONS -lcrypto_openssl.z)
    set(OPENSSL_SSL_LINK_OPTIONS -lssl_openssl.z -lcrypto_openssl.z)
else()
    # The following variables will be restore once find_package is finished.
    set(CMAKE_PREFIX_PATH_TEMP ${CMAKE_PREFIX_PATH})
    set(CMAKE_FIND_LIBRARY_SUFFIXES_TEMP ${CMAKE_FIND_LIBRARY_SUFFIXES})
    get_property(FIND_LIBRARY_USE_LIB64_PATHS_TEMP GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
    # For backward compatibility, --target-lib needs also to be searched.
    foreach(target_lib ${CANGJIE_TARGET_LIB})
        get_filename_component(TARGET_LIB_PREFIX "${target_lib}" DIRECTORY)
        list(APPEND CMAKE_PREFIX_PATH "${TARGET_LIB_PREFIX}")
    endforeach()
    # On Ubuntu, find_package searches /usr first for libraries but compilers search /usr/local first for header
    # files. Because CMake omits system paths from include directories, header files used while building completely
    # depends on the compiler. As a consequence, a build may use a mixture of OpenSSL files from different versions.
    # Here we give /usr/local a higher priority than /usr by adding it into CMAKE_PREFIX_PATH.
    if(CMAKE_HOST_UNIX)
        list(APPEND CMAKE_PREFIX_PATH "/usr/local")
    endif()
    # Due to the vulnerability of OpenSSL library, we always link against shared libraries. Users are able to
    # update OpenSSL by simply replace their local OpenSSL library with a later version.
    if(MINGW)
        set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a")
    elseif(DARWIN)
        set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib")
    else()
        set(CMAKE_FIND_LIBRARY_SUFFIXES ".so")
    endif()
    # OpenSSL library files are located in lib64 folder for x86_64 by default when it's built without configure
    # options, but lib64 folder is not a conventional library folder on Ubuntu (and FIND_LIBRARY_USE_LIB64_PATHS
    # is false when building native targets on Ubuntu). To avoid find_package errors in such cases,
    # FIND_LIBRARY_USE_LIB64_PATHS is set True here manually so lib64 folder can also be searched. From
    # CMake 3.23.0, FindOpenSSL searches lib64 by default. It could be removed if we move to later CMake versions.
    set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS True)
    find_package(OpenSSL 3 REQUIRED COMPONENTS Crypto SSL)
    set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH_TEMP})
    set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_TEMP})
    set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ${FIND_LIBRARY_USE_LIB64_PATHS_TEMP})
    # ld does not support `-l:<filename>` passing style on darwin. It needs to be passed in a standard way.
    if(DARWIN)
        set(OPENSSL_CRYPTO_LIBRARY_LINK_OPTION -lcrypto)
        set(OPENSSL_SSL_LIBRARY_LINK_OPTION -lssl -lcrypto)
    else()
        set(OPENSSL_CRYPTO_LIBRARY_LINK_OPTION -l:$<TARGET_FILE_NAME:OpenSSL::Crypto>)
        set(OPENSSL_SSL_LIBRARY_LINK_OPTION -l:$<TARGET_FILE_NAME:OpenSSL::SSL>)
    endif()
    # Since OpenSSL package is mandatory (marked REQUIRED), it must be found here or processing will be stoped.
    # Note that we are not using OPENSSL_CRYPTO_LIBRARY and OPENSSL_SSL_LIBRARY here. OpenSSL library we are
    # going to link against may not have a soname. Linking with these variables may cause the path of library
    # hard-coded into the final binary. Using -L and -l is necessary in such cases.
    set(OPENSSL_CRYPTO_LINK_OPTIONS -L$<TARGET_FILE_DIR:OpenSSL::Crypto> ${OPENSSL_CRYPTO_LIBRARY_LINK_OPTION})
    set(OPENSSL_SSL_LINK_OPTIONS -L$<TARGET_FILE_DIR:OpenSSL::SSL> ${OPENSSL_SSL_LIBRARY_LINK_OPTION}
        -L$<TARGET_FILE_DIR:OpenSSL::Crypto> ${OPENSSL_CRYPTO_LIBRARY_LINK_OPTION})
endif()