tile/third_party/openssl-cmake/cmake/BuildOpenSSL.cmake
2024-06-11 19:13:30 +08:00

260 lines
11 KiB
CMake

# MIT License
#
# Copyright (c) 2015-2023 The ViaDuck Project
#
# 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.
#
# build openssl locally
# includes
include(ProcessorCount)
include(ExternalProject)
# find packages
find_package(Git REQUIRED)
find_package (Python3 COMPONENTS Interpreter REQUIRED)
# find_package(PythonInterp 3 REQUIRED)
# # used to apply various patches to OpenSSL
find_program(PATCH_PROGRAM patch)
if (NOT PATCH_PROGRAM)
message(FATAL_ERROR "Cannot find patch utility. This is only required for Android cross-compilation but due to script complexity "
"the requirement is always enforced")
endif()
# set variables
ProcessorCount(NUM_JOBS)
set(OS "UNIX")
if (OPENSSL_BUILD_HASH)
set(OPENSSL_CHECK_HASH URL_HASH SHA256=${OPENSSL_BUILD_HASH})
endif()
# if already built, do not build again
if (EXISTS ${OPENSSL_PREFIX})
message(WARNING "Not building OpenSSL again. Remove ${OPENSSL_PREFIX} for rebuild")
else()
if (NOT OPENSSL_BUILD_VERSION)
message(FATAL_ERROR "You must specify OPENSSL_BUILD_VERSION!")
endif()
if (WIN32 AND NOT CROSS)
# yep, windows needs special treatment, but neither cygwin nor msys, since they provide an UNIX-like environment
if (MINGW)
set(OS "WIN32")
message(WARNING "Building on windows is experimental")
find_program(MSYS_BASH "bash.exe" PATHS "C:/Msys/" "C:/MinGW/msys/" PATH_SUFFIXES "/1.0/bin/" "/bin/"
DOC "Path to MSYS installation")
if (NOT MSYS_BASH)
message(FATAL_ERROR "Specify MSYS installation path")
endif(NOT MSYS_BASH)
set(MINGW_MAKE ${CMAKE_MAKE_PROGRAM})
message(WARNING "Assuming your make program is a sibling of your compiler (resides in same directory)")
elseif(NOT (CYGWIN OR MSYS))
message(FATAL_ERROR "Unsupported compiler infrastructure")
endif(MINGW)
set(MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM})
elseif(NOT UNIX)
message(FATAL_ERROR "Unsupported platform")
else()
# for OpenSSL we can only use GNU make, no exotic things like Ninja (MSYS always uses GNU make)
find_program(MAKE_PROGRAM make)
endif()
# save old git values for core.autocrlf and core.eol
execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.autocrlf OUTPUT_VARIABLE GIT_CORE_AUTOCRLF OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.eol OUTPUT_VARIABLE GIT_CORE_EOL OUTPUT_STRIP_TRAILING_WHITESPACE)
# on windows we need to replace path to perl since CreateProcess(..) cannot handle unix paths
if (WIN32 AND NOT CROSS)
set(PERL_PATH_FIX_INSTALL sed -i -- 's/\\/usr\\/bin\\/perl/perl/g' Makefile)
else()
set(PERL_PATH_FIX_INSTALL true)
endif()
# CROSS and CROSS_ANDROID cannot both be set (because of internal reasons)
if (CROSS AND CROSS_ANDROID)
# if user set CROSS_ANDROID and CROSS we assume he wants CROSS_ANDROID, so set CROSS to OFF
set(CROSS OFF)
endif()
if (CROSS_ANDROID)
set(OS "LINUX_CROSS_ANDROID")
endif()
# python helper script for corrent building environment
set(BUILD_ENV_TOOL ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/building_env.py
--bash "${MSYS_BASH}" --make "${MINGW_MAKE}" --envfile "${CMAKE_CURRENT_BINARY_DIR}/buildenv.txt" ${OS})
# user-specified modules
set(CONFIGURE_OPENSSL_MODULES ${OPENSSL_MODULES})
# additional configure script parameters
set(CONFIGURE_OPENSSL_PARAMS --libdir=lib)
if (OPENSSL_DEBUG_BUILD)
set(CONFIGURE_OPENSSL_PARAMS "${CONFIGURE_OPENSSL_PARAMS} no-asm -g3 -O0 -fno-omit-frame-pointer -fno-inline-functions")
endif()
if (OPENSSL_RPATH)
# ridiculous escaping required to pass through cmake, one shell, one makefile and another shell.
# \\\\ in shell, \\ in makefile
string(REPLACE "\\" "\\\\\\\\" OPENSSL_RPATH_ESCAPED ${OPENSSL_RPATH})
# \\$\$ in shell, \$$ in makefile
string(REPLACE "\$" "\\\\\$\\\$" OPENSSL_RPATH_ESCAPED ${OPENSSL_RPATH_ESCAPED}) # \$$ in makefile
set(CONFIGURE_OPENSSL_PARAMS "${CONFIGURE_OPENSSL_PARAMS} -Wl,-rpath=${OPENSSL_RPATH_ESCAPED}")
endif()
# set install command depending of choice on man page generation
if (OPENSSL_INSTALL_MAN)
set(INSTALL_OPENSSL_MAN "install_docs")
endif()
# disable building tests
if (NOT OPENSSL_ENABLE_TESTS)
set(CONFIGURE_OPENSSL_MODULES ${CONFIGURE_OPENSSL_MODULES} no-tests)
set(COMMAND_TEST "true")
endif()
# cross-compiling
if (CROSS)
set(COMMAND_CONFIGURE ./Configure ${CONFIGURE_OPENSSL_PARAMS} --cross-compile-prefix=${CROSS_PREFIX} ${CROSS_TARGET}
${CONFIGURE_OPENSSL_MODULES} --prefix=/usr/local/)
set(COMMAND_TEST "true")
elseif(CROSS_ANDROID)
# required environment configuration is already set (by e.g. ndk) so no need to fiddle around with all the OpenSSL options ...
if (NOT ANDROID)
message(FATAL_ERROR "Use NDK cmake toolchain or cmake android autoconfig")
endif()
# arch options
if (ARMEABI_V7A)
set(OPENSSL_PLATFORM "arm")
set(CONFIGURE_OPENSSL_PARAMS ${CONFIGURE_OPENSSL_PARAMS} "-march=armv7-a")
else()
if (CMAKE_ANDROID_ARCH_ABI MATCHES "arm64-v8a")
set(OPENSSL_PLATFORM "arm64")
else()
set(OPENSSL_PLATFORM ${CMAKE_ANDROID_ARCH_ABI})
endif()
endif()
# collect options to pass via ENV to openssl configure
set(FORWARD_ANDROID_NDK "${ANDROID_NDK}")
# silence warnings about unused arguments (Clang specific)
set(FORWARD_CFLAGS "${CMAKE_C_FLAGS} -Qunused-arguments")
set(FORWARD_CXXFLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments")
set(FORWARD_LDFLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
set(FORWARD_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin/:${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_NAME}/bin/")
# Android specific configuration options
set(CONFIGURE_OPENSSL_MODULES ${CONFIGURE_OPENSSL_MODULES} no-hw)
set(COMMAND_CONFIGURE ./Configure android-${OPENSSL_PLATFORM} ${CONFIGURE_OPENSSL_PARAMS} ${CONFIGURE_OPENSSL_MODULES})
set(COMMAND_TEST "true")
else() # detect host system automatically
set(COMMAND_CONFIGURE ./config ${CONFIGURE_OPENSSL_PARAMS} ${CONFIGURE_OPENSSL_MODULES})
if (NOT COMMAND_TEST)
set(COMMAND_TEST ${BUILD_ENV_TOOL} <SOURCE_DIR> -- ${MAKE_PROGRAM} test)
endif()
endif()
# build OPENSSL_PATCH_COMMAND
include(PatchOpenSSL)
# file(ARCHIVE_EXTRACT INPUT ${CMAKE_CURRENT_SOURCE_DIR}/openssl-1.1.1u.tar.gz DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/openssl-prefix/)
# add openssl target
ExternalProject_Add(openssl
#URL https://mirror.viaduck.org/openssl/openssl-${OPENSSL_BUILD_VERSION}.tar.gz
#URL http://127.0.0.1:7788/openssl-${OPENSSL_BUILD_VERSION}.tar.gz
URL ${CMAKE_CURRENT_SOURCE_DIR}/openssl-1.1.1u.tar.gz
${OPENSSL_CHECK_HASH}
UPDATE_COMMAND ""
CONFIGURE_COMMAND ${BUILD_ENV_TOOL} <SOURCE_DIR> -- ${COMMAND_CONFIGURE}
${OPENSSL_PATCH_COMMAND}
BUILD_COMMAND ${BUILD_ENV_TOOL} <SOURCE_DIR> -- ${MAKE_PROGRAM} -j ${NUM_JOBS}
BUILD_BYPRODUCTS ${OPENSSL_BYPRODUCTS}
TEST_BEFORE_INSTALL 1
TEST_COMMAND ${COMMAND_TEST}
INSTALL_COMMAND ${BUILD_ENV_TOOL} <SOURCE_DIR> -- ${PERL_PATH_FIX_INSTALL}
COMMAND ${BUILD_ENV_TOOL} <SOURCE_DIR> -- ${MAKE_PROGRAM} DESTDIR=${OPENSSL_PREFIX} install_sw ${INSTALL_OPENSSL_MAN}
COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR} ${CMAKE_BINARY_DIR} # force CMake-reload
LOG_INSTALL 1
)
# set git config values to openssl requirements (no impact on linux though)
ExternalProject_Add_Step(openssl setGitConfig
COMMAND ${GIT_EXECUTABLE} config --global core.autocrlf false
COMMAND ${GIT_EXECUTABLE} config --global core.eol lf
DEPENDEES
DEPENDERS download
ALWAYS ON
INDEPENDENT TRUE
)
# set, don't abort if it fails (due to variables being empty). To realize this we must only call git if the configs
# are set globally, otherwise do a no-op command ("echo 1", since "true" is not available everywhere)
if (GIT_CORE_AUTOCRLF)
set (GIT_CORE_AUTOCRLF_CMD ${GIT_EXECUTABLE} config --global core.autocrlf ${GIT_CORE_AUTOCRLF})
else()
set (GIT_CORE_AUTOCRLF_CMD echo)
endif()
if (GIT_CORE_EOL)
set (GIT_CORE_EOL_CMD ${GIT_EXECUTABLE} config --global core.eol ${GIT_CORE_EOL})
else()
set (GIT_CORE_EOL_CMD echo)
endif()
##
# set git config values to previous values
ExternalProject_Add_Step(openssl restoreGitConfig
# unset first (is required, since old value could be omitted, which wouldn't take any effect in "set"
COMMAND ${GIT_EXECUTABLE} config --global --unset core.autocrlf
COMMAND ${GIT_EXECUTABLE} config --global --unset core.eol
COMMAND ${GIT_CORE_AUTOCRLF_CMD}
COMMAND ${GIT_CORE_EOL_CMD}
DEPENDEES download
DEPENDERS configure
ALWAYS ON
)
# write all "FORWARD_" variables with escaped quotes to file, is picked up by python script
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if (_variableName MATCHES "^FORWARD_")
string(REPLACE "FORWARD_" "" _envName ${_variableName})
string(REPLACE "\"" "\\\"" _envValue "${${_variableName}}")
set(OUT_FILE "${OUT_FILE}${_envName}=\"${_envValue}\"\n")
endif()
endforeach()
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/buildenv.txt ${OUT_FILE})
endif()