Skip to content

Commit

Permalink
build: make feature flags consistent (#3921)
Browse files Browse the repository at this point in the history
  • Loading branch information
camshaft authored Jun 2, 2023
1 parent b9c4d60 commit 6c38bde
Show file tree
Hide file tree
Showing 34 changed files with 201 additions and 363 deletions.
322 changes: 101 additions & 221 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ option(S2N_INTERN_LIBCRYPTO "This ensures that s2n-tls is compiled and deployed
version of libcrypto by interning the code and hiding symbols. This also enables s2n-tls to be
loaded in an application with an otherwise conflicting libcrypto version." OFF)
option(S2N_LTO, "Enables link time optimizations when building s2n-tls." OFF)
option(S2N_STACKTRACE "Enables stacktrace functionality in s2n-tls." ON)
option(S2N_STACKTRACE "Enables stacktrace functionality in s2n-tls. Note that this functionality is
only available on platforms that support execinfo." ON)
option(COVERAGE "Enable profiling collection for code coverage calculation" OFF)
option(S2N_INTEG_TESTS "Enable the integrationv2 tests" OFF)
option(S2N_FAST_INTEG_TESTS "Enable the integrationv2 with more parallelism, only has effect if S2N_INTEG_TESTS=ON" OFF)
Expand Down Expand Up @@ -112,114 +113,6 @@ else()
find_package(Threads REQUIRED)
endif()

if(S2N_NO_PQ_ASM)
message(STATUS "S2N_NO_PQ_ASM flag was detected - disabling PQ crypto assembly code")
else()
enable_language(ASM)

# Kyber Round-3 code has several different optimizations which require
# specific compiler flags to be supported by the compiler.
# So for each needed instruction set extension we check if the compiler
# supports it and set proper compiler flags to be added later to the
# Kyber compilation units.
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(x86_64|amd64|AMD64)$")

set(KYBER512R3_AVX2_BMI2_FLAGS "-mavx2 -mavx -mbmi2")
try_compile(KYBER512R3_AVX2_BMI2_SUPPORTED
${CMAKE_BINARY_DIR}
"${CMAKE_CURRENT_LIST_DIR}/tests/features/noop_main.c"
COMPILE_DEFINITIONS ${KYBER512R3_AVX2_BMI2_FLAGS})

try_compile(KYBER512R3_M256_INTRINSICS_SUPPORTED
${CMAKE_BINARY_DIR}
"${CMAKE_CURRENT_LIST_DIR}/tests/features/m256_intrinsics.c")

# Some platforms support -mavx2 flag but not m256 intrinsics required to use them. Only enable Kyber assembly
# optimizations if both are supported. See https://github.com/aws/s2n-tls/pull/3005 for more info.
if(KYBER512R3_AVX2_BMI2_SUPPORTED AND KYBER512R3_M256_INTRINSICS_SUPPORTED)
set(KYBER512R3_AVX2_BMI2_OPT_SUPPORTED ON)
endif()
endif()
endif()

if(KYBER512R3_AVX2_BMI2_OPT_SUPPORTED)
FILE(GLOB KYBER512R3_AVX2_BMI2_ASM_SRCS "pq-crypto/kyber_r3/*_avx2.S")
list(APPEND PQ_SRC ${KYBER512R3_AVX2_BMI2_ASM_SRCS})
endif()

# Probe for execinfo.h extensions (not present on some systems, notably android)
include(CheckCSourceCompiles)

# Determine if execinfo.h is available
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
try_compile(
S2N_HAVE_EXECINFO
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/execinfo.c"
LINK_LIBRARIES execinfo
)
else()
try_compile(
S2N_HAVE_EXECINFO
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/execinfo.c"
)
endif()

# Determine if cpuid.h is available
try_compile(
S2N_CPUID_AVAILABLE
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/cpuid.c"
)

# Determine if features.h is available
try_compile(
S2N_FEATURES_AVAILABLE
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/features.c"
)

# Determine if __attribute__((fallthrough)) is available
try_compile(
FALL_THROUGH_SUPPORTED
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/fallthrough.c"
COMPILE_DEFINITIONS "-Werror"
)

# Determine if __restrict__ is available
try_compile(
__RESTRICT__SUPPORTED
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/__restrict__.c"
COMPILE_DEFINITIONS "-Werror"
)

# Determine if madvise() is available
try_compile(
MADVISE_SUPPORTED
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/madvise.c"
COMPILE_DEFINITIONS "-Werror"
)

# Determine if minherit() is available
try_compile(
MINHERIT_SUPPORTED
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/minherit.c"
COMPILE_DEFINITIONS "-Werror"
)

# Determine if clone() is available
try_compile(
CLONE_SUPPORTED
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/clone.c"
COMPILE_DEFINITIONS "-Werror"
)

if(APPLE)
set(OS_LIBS c Threads::Threads)
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
Expand Down Expand Up @@ -300,7 +193,7 @@ if(NOT APPLE)
endif()

if(S2N_NO_PQ)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_NO_PQ)
add_definitions(-DS2N_NO_PQ)
endif()

# Whether to fail the build when compiling s2n's portable C code with non-portable assembly optimizations. Doing this
Expand All @@ -312,33 +205,11 @@ if(S2N_BLOCK_NONPORTABLE_OPTIMIZATIONS)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_BLOCK_NONPORTABLE_OPTIMIZATIONS=1)
endif()

if(KYBER512R3_AVX2_BMI2_OPT_SUPPORTED)
FILE(GLOB KYBER512R3_AVX2_BMI2_SRCS "pq-crypto/kyber_r3/*_avx2.c")
set_source_files_properties(${KYBER512R3_AVX2_BMI2_SRCS} PROPERTIES COMPILE_FLAGS ${KYBER512R3_AVX2_BMI2_FLAGS})
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_KYBER512R3_AVX2_BMI2)

message(STATUS "Enabling Kyber_R3 x86_64 optimizations")
endif()

if(S2N_HAVE_EXECINFO AND S2N_STACKTRACE)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_STACKTRACE)
else()
message(STATUS "Disabling stacktrace functionality")
endif()

if(S2N_CPUID_AVAILABLE)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_CPUID_AVAILABLE)
endif()

if(S2N_FEATURES_AVAILABLE)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_FEATURES_AVAILABLE)
endif()

target_compile_options(${PROJECT_NAME} PUBLIC -fPIC)

target_compile_definitions(${PROJECT_NAME} PRIVATE -D_POSIX_C_SOURCE=200809L)
add_definitions(-D_POSIX_C_SOURCE=200809L)
if(CMAKE_BUILD_TYPE MATCHES Release)
target_compile_definitions(${PROJECT_NAME} PRIVATE -D_FORTIFY_SOURCE=2)
add_definitions(-D_FORTIFY_SOURCE=2)
endif()

if(NO_STACK_PROTECTOR)
Expand All @@ -349,29 +220,6 @@ if(S2N_UNSAFE_FUZZING_MODE)
target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize-coverage=trace-pc-guard -fsanitize=address,undefined,leak -fuse-ld=gold -DS2N_ADDRESS_SANITIZER=1)
endif()

if (FALL_THROUGH_SUPPORTED)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_FALL_THROUGH_SUPPORTED)
endif()

if (__RESTRICT__SUPPORTED)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N___RESTRICT__SUPPORTED)
endif()

if (MADVISE_SUPPORTED)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_MADVISE_SUPPORTED)
message(STATUS "madvise() support detected")
endif()

if (MINHERIT_SUPPORTED)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_MINHERIT_SUPPORTED)
message(STATUS "minherit() support detected")
endif()

if (CLONE_SUPPORTED)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_CLONE_SUPPORTED)
message(STATUS "clone() support detected")
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")

if (NOT $ENV{S2N_LIBCRYPTO} MATCHES "awslc")
Expand Down Expand Up @@ -416,86 +264,118 @@ if (S2N_INTERN_LIBCRYPTO)
message(STATUS "Enabling libcrypto interning")
endif()

# Determine if EVP_md5_sha1 is available in libcrypto
try_compile(
LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/evp_md5_sha1.c"
LINK_LIBRARIES ${LINK_LIB} ${OS_LIBS}
)
if (LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH)
if (NOT DEFINED CMAKE_AR)
message(STATUS "CMAKE_AR undefined, setting to `ar` by default")
SET(CMAKE_AR ar)
else()
message(STATUS "CMAKE_AR found: ${CMAKE_AR}")
endif()

# Determine if RC4 is available in libcrypto
try_compile(
LIBCRYPTO_SUPPORTS_EVP_RC4
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/evp_rc4.c"
LINK_LIBRARIES ${LINK_LIB} ${OS_LIBS}
)
if (NOT DEFINED CMAKE_RANLIB)
message(STATUS "CMAKE_RANLIB undefined, setting to `ranlib` by default")
SET(CMAKE_RANLIB ranlib)
else()
message(STATUS "CMAKE_RANLIB found: ${CMAKE_RANLIB}")
endif()

if (LIBCRYPTO_SUPPORTS_EVP_RC4)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_LIBCRYPTO_SUPPORTS_EVP_RC4)
if (NOT DEFINED CMAKE_OBJCOPY)
message(STATUS "CMAKE_OBJCOPY undefined, setting to `objcopy` by default")
SET(CMAKE_OBJCOPY objcopy)
else()
message(STATUS "CMAKE_OBJCOPY found: ${CMAKE_OBJCOPY}")
endif()

# Determine if EVP_MD_CTX_set_pkey_ctx is available in libcrypto
try_compile(
LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
# Sets the result of the feature probe to `IS_AVAILABLE`
function(feature_probe_result PROBE_NAME IS_AVAILABLE)
# normalize the boolean value
if(IS_AVAILABLE)
set(NORMALIZED TRUE)
else()
set(NORMALIZED FALSE)
endif()

# indicate the status of the probe
message(STATUS "feature ${PROBE_NAME}: ${NORMALIZED}")
# set the probe result in the parent scope for other probes
set(${PROBE_NAME} ${NORMALIZED} PARENT_SCOPE)

# define the probe if available
if(NORMALIZED)
add_definitions(-D${PROBE_NAME})
endif()
endfunction()

# Tries to compile a feature probe and initializes the corresponding flags
function(feature_probe PROBE_NAME)
# Load the probe's flags
file(READ "${CMAKE_CURRENT_LIST_DIR}/tests/features/${PROBE_NAME}.flags" PROBE_FILE)
string(REPLACE "\n" "" PROBE_FLAGS "${PROBE_FILE}")

# Try to compile the probe with the given flags
try_compile(
IS_AVAILABLE
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/evp_md_ctx_set_pkey_ctx.c"
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/${PROBE_NAME}.c"
LINK_LIBRARIES ${LINK_LIB} ${OS_LIBS}
CMAKE_FLAGS ${ADDITIONAL_FLAGS}
)
COMPILE_DEFINITIONS -c ${PROBE_FLAGS}
${ARGN}
)

if (LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX)
endif()
# Set the result of the probe
feature_probe_result(${PROBE_NAME} ${IS_AVAILABLE})

# Determine if KEM Kyber512 implementation from AWS-LC is available
try_compile(
LIBCRYPTO_SUPPORTS_EVP_KEM_KYBER_512
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/evp_kem_kyber_512.c"
LINK_LIBRARIES ${LINK_LIB} ${OS_LIBS}
COMPILE_DEFINITIONS "-Werror"
)
# Make sure the variable is set in the parent scope
set(${PROBE_NAME} ${IS_AVAILABLE} PARENT_SCOPE)

if(LIBCRYPTO_SUPPORTS_EVP_KEM_KYBER_512)
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_LIBCRYPTO_SUPPORTS_KYBER512)
endif()
# Set the flags that we used for the probe
set(${PROBE_NAME}_FLAGS ${PROBE_FLAGS} PARENT_SCOPE)
endfunction()

# Determine if kTLS is supported
try_compile(
PLATFORM_SUPPORTS_KTLS
${CMAKE_BINARY_DIR}
SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/ktls.c"
)
if(PLATFORM_SUPPORTS_KTLS)
message(STATUS "feature probe: kTLS supported")
target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_PLATFORM_SUPPORTS_KTLS)
endif()
# Iterate over all of the features and try to compile them
FILE(GLOB FEATURE_SRCS "${CMAKE_CURRENT_LIST_DIR}/tests/features/*.c")
list(SORT FEATURE_SRCS)
foreach(file ${FEATURE_SRCS})
get_filename_component(feature_name ${file} NAME_WE)
feature_probe(${feature_name})
endforeach()

if (NOT DEFINED CMAKE_AR)
message(STATUS "CMAKE_AR undefined, setting to `ar` by default")
SET(CMAKE_AR ar)
else()
message(STATUS "CMAKE_AR found: ${CMAKE_AR}")
# FreeBSD might need to link to execinfo explicitly
if(NOT S2N_EXECINFO_AVAILABLE AND CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
feature_probe(S2N_EXECINFO_AVAILABLE LINK_LIBRARIES execinfo)
endif()

if (NOT DEFINED CMAKE_RANLIB)
message(STATUS "CMAKE_RANLIB undefined, setting to `ranlib` by default")
SET(CMAKE_RANLIB ranlib)
else()
message(STATUS "CMAKE_RANLIB found: ${CMAKE_RANLIB}")
# Stack traces are only available if execinfo is
if (NOT S2N_EXECINFO_AVAILABLE)
set(S2N_STACKTRACE FALSE)
endif()
feature_probe_result(S2N_STACKTRACE ${S2N_STACKTRACE})

if (NOT DEFINED CMAKE_OBJCOPY)
message(STATUS "CMAKE_OBJCOPY undefined, setting to `objcopy` by default")
SET(CMAKE_OBJCOPY objcopy)
else()
message(STATUS "CMAKE_OBJCOPY found: ${CMAKE_OBJCOPY}")
set(S2N_KYBER512R3_AVX2_BMI2 FALSE)
if(NOT S2N_NO_PQ_ASM)
# Kyber Round-3 code has several different optimizations which require
# specific compiler flags to be supported by the compiler.
# So for each needed instruction set extension we check if the compiler
# supports it and set proper compiler flags to be added later to the
# Kyber compilation units.
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(x86_64|amd64|AMD64)$")
# Some platforms support -mavx2 flag but not m256 intrinsics required to use them. Only enable Kyber assembly
# optimizations if both are supported. See https://github.com/aws/s2n-tls/pull/3005 for more info.
if(S2N_KYBER512R3_AVX2_BMI2_SUPPORTED AND S2N_KYBER512R3_M256_INTRINSICS_SUPPORTED)
set(S2N_KYBER512R3_AVX2_BMI2 TRUE)
enable_language(ASM)

# add the assembly files to the project
FILE(GLOB KYBER512R3_AVX2_BMI2_ASM_SRCS "pq-crypto/kyber_r3/*_avx2.S")
target_sources(${PROJECT_NAME} PRIVATE ${KYBER512R3_AVX2_BMI2_ASM_SRCS})

# compile the C files with avx flags
FILE(GLOB KYBER512R3_AVX2_BMI2_SRCS "pq-crypto/kyber_r3/*_avx2.c")
set_source_files_properties(${KYBER512R3_AVX2_BMI2_SRCS} PROPERTIES COMPILE_FLAGS ${S2N_KYBER512R3_AVX2_BMI2_SUPPORTED_FLAGS})
endif()
endif()
endif()
feature_probe_result(S2N_KYBER512R3_AVX2_BMI2 ${S2N_KYBER512R3_AVX2_BMI2})

if (S2N_INTERN_LIBCRYPTO)

Expand Down Expand Up @@ -658,14 +538,14 @@ if (BUILD_TESTING)
target_link_libraries(s2nc ${PROJECT_NAME})

target_include_directories(s2nc PRIVATE api)
target_compile_options(s2nc PRIVATE -std=gnu99 -D_POSIX_C_SOURCE=200112L)
target_compile_options(s2nc PRIVATE -std=gnu99)


add_executable(s2nd "bin/s2nd.c" "bin/echo.c" "bin/https.c" "bin/common.c")
target_link_libraries(s2nd ${PROJECT_NAME})

target_include_directories(s2nd PRIVATE api)
target_compile_options(s2nd PRIVATE -std=gnu99 -D_POSIX_C_SOURCE=200112L)
target_compile_options(s2nd PRIVATE -std=gnu99)

if(S2N_LTO)
target_compile_options(s2nc PRIVATE -flto)
Expand Down
Loading

0 comments on commit 6c38bde

Please sign in to comment.