# This file is part of the openHiTLS project.
#
# openHiTLS is licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
include_guard(GLOBAL)
include(CheckCCompilerFlag)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# Default compile options for HiTLS.
set(_hitls_compile_options_list
# CC_OVERALL_FLAGS
-pipe
# CC_WARN_FLAGS
-Werror -Wextra -Wcast-qual -Wall -Wfloat-equal -Wshadow -Wformat=2
# CC_LANGUAGE_FLAGS
-fsigned-char
# CC_CDG_FLAGS
-fno-common
# CC_OPT_FLAGS
-fno-strict-aliasing -fno-omit-frame-pointer
# CC_SEC_FLAGS
-fstack-protector-strong
)
# Default link flags for HiTLS
set(_hitls_shared_link_flags_list "")
set(_hitls_exe_link_flags_list "")
if(CMAKE_BUILD_TYPE)
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
# Add `-D_FORTIFY_SOURCE=2` if the build type is not Debug
list(INSERT _hitls_compile_options_list 0 "-D_FORTIFY_SOURCE=2")
endif()
else()
# If `CMAKE_BUILD_TYPE` is unset, CMake does not apply any optimization flags by default,
# so we add -O2 as a safe fallback. We also add -D_FORTIFY_SOURCE=2 as a safe default for non-Debug builds.
list(INSERT _hitls_compile_options_list 0 "-D_FORTIFY_SOURCE=2;-O2")
endif()
# gcc specific options
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
list(APPEND _hitls_compile_options_list
# CC_WARN_FLAGS
-Wdate-time
# CC_SEC_FLAGS
--param=ssp-buffer-size=4
)
# clang/apple-clang specific options
elseif(CMAKE_C_COMPILER_ID MATCHES "^(Clang|AppleClang)$")
list(APPEND _hitls_compile_options_list
# CC_SEC_FLAGS
-Wno-unused-command-line-argument
)
endif()
# -fstack-clash-protection: prevents stack-clash exploits by inserting stack probes
# that ensure the guard page is always touched before a large stack allocation,
# closing the window where stack and heap can silently overlap.
# Available in GCC >= 8 and Clang >= 11.
check_c_compiler_flag(-fstack-clash-protection _HAS_STACK_CLASH_PROTECTION)
if(_HAS_STACK_CLASH_PROTECTION)
list(APPEND _hitls_compile_options_list -fstack-clash-protection)
endif()
# -fcf-protection=full: Intel CET (IBT + shadow stack) to defeat ROP/JOP attacks.
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|x86|i[3-6]86|amd64")
check_c_compiler_flag(-fcf-protection=full _HAS_CF_PROTECTION)
if(_HAS_CF_PROTECTION)
list(APPEND _hitls_compile_options_list -fcf-protection=full)
endif()
endif()
# -mbranch-protection=standard: AArch64 BTI + PAC-RET, the ARM equivalent of Intel CET.
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$")
check_c_compiler_flag(-mbranch-protection=standard _HAS_BRANCH_PROTECTION)
if(_HAS_BRANCH_PROTECTION)
list(APPEND _hitls_compile_options_list -mbranch-protection=standard)
endif()
endif()
# Linker flags based on detected linker
set(_hitls_public_link_flags_list "")
execute_process(
COMMAND ${CMAKE_LINKER} --version
OUTPUT_VARIABLE _hitls_linker_version
ERROR_VARIABLE _hitls_linker_version
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(_hitls_linker_version MATCHES "GNU gold|GNU ld|GNU Binutils")
list(APPEND _hitls_exe_link_flags_list -pie)
list(APPEND _hitls_public_link_flags_list
-Wl,-z,noexecstack
-Wl,-z,relro
-Wl,-z,now
-Wl,--build-id=none
)
list(APPEND _hitls_shared_link_flags_list -Wl,--no-undefined)
if(_hitls_linker_version MATCHES "GNU gold")
list(APPEND _hitls_public_link_flags_list
-Wl,--threads
-Wl,--thread-count=4
)
endif()
elseif(_hitls_linker_version MATCHES "ld64" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# macOS 64-bit executables are always PIE by default (enforced by ld64 since macOS 10.7);
# explicitly passing -pie is redundant and ld64 may warn about it, so it is omitted here.
list(APPEND _hitls_public_link_flags_list -Wl,-dead_strip)
list(APPEND _hitls_shared_link_flags_list -Wl,-undefined,error)
elseif(_hitls_linker_version MATCHES "LLD")
list(APPEND _hitls_exe_link_flags_list -pie)
list(APPEND _hitls_public_link_flags_list
-Wl,-z,noexecstack
-Wl,-z,relro
-Wl,-z,now
-Wl,--build-id=none
-Wl,--as-needed
)
list(APPEND _hitls_shared_link_flags_list -Wl,--no-undefined)
endif()
list(APPEND _hitls_shared_link_flags_list ${_hitls_public_link_flags_list})
list(APPEND _hitls_exe_link_flags_list ${_hitls_public_link_flags_list})
# User-overridable CACHE variables.
# Override via cmake -DHITLS_COMPILE_OPTIONS="flag1;flag2" (semicolons as CMake list separators).
# CMAKE_C_FLAGS / CMAKE_SHARED_LINKER_FLAGS / CMAKE_EXE_LINKER_FLAGS are NOT modified,
# so user-supplied values for those variables are fully preserved.
set(HITLS_COMPILE_OPTIONS "${_hitls_compile_options_list}" CACHE STRING
"Compile options applied to all HiTLS targets (via add_compile_options).")
set(HITLS_SHARED_LINKER_FLAGS "${_hitls_shared_link_flags_list}" CACHE STRING
"Linker flags applied only to HiTLS shared library targets via target_link_options.")
set(HITLS_EXE_LINKER_FLAGS "${_hitls_exe_link_flags_list}" CACHE STRING
"Linker flags applied only to HiTLS executable targets via target_link_options.")
# Allow users to add or remove compile options via cache variables.
set(_HITLS_COMPILE_OPTIONS_DEL "" CACHE STRING "Compile options to remove from defaults (optional)")
if(_HITLS_COMPILE_OPTIONS_DEL)
separate_arguments(_hitls_compile_options_del_list UNIX_COMMAND "${_HITLS_COMPILE_OPTIONS_DEL}")
list(REMOVE_ITEM HITLS_COMPILE_OPTIONS ${_hitls_compile_options_del_list})
set(HITLS_COMPILE_OPTIONS "${HITLS_COMPILE_OPTIONS}" CACHE STRING
"Compile options applied to all HiTLS targets (via add_compile_options).")
endif()
# Apply global compile options
add_compile_options(${HITLS_COMPILE_OPTIONS})
message(STATUS "====== HiTLS Build Options ======")
message(STATUS "CMAKE_POSITION_INDEPENDENT_CODE : ${CMAKE_POSITION_INDEPENDENT_CODE}")
message(STATUS "HITLS_COMPILE_OPTIONS : ${HITLS_COMPILE_OPTIONS}")
message(STATUS "HITLS_SHARED_LINKER_FLAGS : ${HITLS_SHARED_LINKER_FLAGS}")
message(STATUS "HITLS_EXE_LINKER_FLAGS : ${HITLS_EXE_LINKER_FLAGS}")
message(STATUS "CMAKE_C_FLAGS : ${CMAKE_C_FLAGS}")
message(STATUS "CMAKE_ASM_FLAGS : ${CMAKE_ASM_FLAGS}")
message(STATUS "CMAKE_SHARED_LINKER_FLAGS : ${CMAKE_SHARED_LINKER_FLAGS}")
message(STATUS "CMAKE_EXE_LINKER_FLAGS : ${CMAKE_EXE_LINKER_FLAGS}")
# Optimization level comes from CMAKE_C_FLAGS_<CONFIG>
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "CMAKE_C_FLAGS_DEBUG : ${CMAKE_C_FLAGS_DEBUG}")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
message(STATUS "CMAKE_C_FLAGS_RELEASE : ${CMAKE_C_FLAGS_RELEASE}")
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
message(STATUS "CMAKE_C_FLAGS_RELWITHDEBINFO : ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
message(STATUS "CMAKE_C_FLAGS_MINSIZEREL : ${CMAKE_C_FLAGS_MINSIZEREL}")
endif()
message(STATUS "=================================")