From a8d753667c312ed1b29b115fe8701931f32d9ea5 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Thu, 12 Sep 2024 09:49:37 +0800 Subject: [PATCH] build: enable Seastar to build shared and static libs in a single build before this change, we respect the CMake variable named `BUILD_SHARED_LIBS`, and build shared libraries if it is set, build static libraries otherwise. but this model cannot fulfill the needs of a parent project which needs to build both static and shared seastar libraries with different configuration in a multi-config generator settings. as `BUILD_SHARED_LIBS` is a CMake variable which cannot be changed at build time, and hence cannot be assigned with different values using generator expression. so, in this change, we add two options - Seastar_BUILD_STATIC_LIBS - Seastar_BUILD_SHARED_LIBS to configure if the build should generated static libraries and shared libraries respectively. but `BUILD_SHARED_LIBS` is still supported, and the behavior is backward compatible. the only user-visible differences are, the libraries of - seastar - seastar_testing - seastar_perf_testing are now aliases of the targets which builds the static or shared libraries. so one cannot build "seastar" as a target anymore, but should specify which library to build: ``` $ cmake --build build --target seastar # does not work anymore $ cmake --build build --target seastar-static $ cmake --build build --target seastar-shared ``` the reason is the limit of an ALIAS library, which cannot be used as a target. but we still need to use a non-interface library to generate .pc file, where, for instance, we use `$` for the library list of a certain Seastar library. but a CMake-based project including seastar can still link against it using "seastar" as a library. please note, in d8a70b39, we pass `--ftls-mode=initial-exec` when building the tree, to address the problem of recursive call of malloc when using seastar allocator. but we cannot use different compiling options when building both shared libraries and static libraries, so we always pass this option as long as `BUILD_SHARED_LIBS` OR `Seastar_BUILD_SHARED_LIBS` is set *and* when we are building dev/release modes. as these two modes enables the seastar allocator. this should not hurt the overall performance, as we are not using global-dynamic mode, but initial-exec. this is verified using ```console $ cmake \ -DCMAKE_CONFIGURATION_TYPES="Debug;RelWithDebInfo" \ -DCMAKE_CROSS_CONFIGS="Debug;RelWithDebInfo" \ -DCMAKE_DEFAULT_CONFIGS="Debug;RelWithDebInfo" \ -DSeastar_BUILD_SHARED_LIBS=ON \ -DSeastar_BUILD_STATIC_LIBS=ON \ -G "Ninja Multi-Config" -B build -S . $ cmake --build build --config RelWithDebInfo --target seastar-static $ readelf -r build/CMakeFiles/seastar-objects.dir/RelWithDebInfo/src/core/reactor.cc.o| \ grep -i tls | tr -s ' ' | cut -d' ' -f 3,5 | uniq R_X86_64_TPOFF32 __tls_guard R_X86_64_PLT32 _ZStlsRSoRKNSt15_[...] ``` and ```console $ cmake -DCMAKE_BUILD_TYPE="RelWithDebInfo" -G "Ninja" -B build -S . $ cmake --build build --target seastar-static $ readelf -r build/CMakeFiles/seastar-objects.dir/src/core/reactor.cc.o| \ grep -i tls | tr -s ' ' | cut -d' ' -f 3,5 | uniq R_X86_64_TPOFF32 __tls_guard R_X86_64_PLT32 _ZStlsRSoRKNSt15_[...] ``` so the TLS variables are using "TPOFF32" relocation type, in general, it implies the initial-exec TLS model. the PLT32 is not specific TLS, it's more related to external symbols linkages. Refs scylladb/scylladb#2717 Signed-off-by: Kefu Chai --- CMakeLists.txt | 174 +++++++++++++++++++++++------------ cmake/CheckLibc.cmake | 6 +- cmake/SeastarConfig.cmake.in | 17 +++- 3 files changed, 133 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e1bb64d189..68321b9522c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,6 +320,61 @@ set (Seastar_TEST_TIMEOUT option (BUILD_SHARED_LIBS "Build seastar library as shared libraries instead of static" OFF) +cmake_dependent_option (Seastar_BUILD_SHARED_LIBS + "Build Seastar as shared libraries" OFF + "NOT DEFINED BUILD_SHARED_LIB" OFF) +cmake_dependent_option (Seastar_BUILD_STATIC_LIBS + "Build Seastar as static libraries" ON + "NOT DEFINED BUILD_SHARED_LIB" OFF) +if (NOT (Seastar_BUILD_SHARED_LIBS OR Seastar_BUILD_STATIC_LIBS)) + message (FATAL_ERROR "Seastar_BUILD_STATIC_LIBS and Seastar_BUILD_STATIC_LIBS cannot both be disabled") +endif () + +function (seastar_add_library name objects) + if (Seastar_BUILD_STATIC_LIBS) + list (APPEND types static) + endif () + if (Seastar_BUILD_SHARED_LIBS) + list (APPEND types shared) + endif () + + foreach (type ${types}) + string (TOUPPER ${type} TYPE) + set (fullname ${name}-${type}) + add_library (${fullname} ${TYPE} $) + list (APPEND seastar-libraries ${fullname}) + + set_target_properties (${fullname} PROPERTIES + OUTPUT_NAME "${name}") + # add_library() does not populate the property of the included sources + # to the library target being added, so we need to do this manually. + foreach (property + INTERFACE_COMPILE_DEFINITIONS + INTERFACE_COMPILE_FEATURES + INTERFACE_COMPILE_OPTIONS + INTERFACE_INCLUDE_DIRECTORIES + INTERFACE_LINK_LIBRARIES + LINK_LIBRARIES) + get_target_property (value ${objects} ${property}) + if (value) + set_target_properties (${fullname} + PROPERTIES ${property} "${value}") + endif () + endforeach () + + add_library (Seastar::${fullname} ALIAS ${fullname}) + + # make sure ${name} and Seastar:${name} always exist, and we prefer + # the libraries if they are available. + if (NOT TARGET ${name}) + add_library (${name} ALIAS ${fullname}) + add_library (Seastar::${name} ALIAS ${fullname}) + endif () + endforeach (type ${types}) + + set (seastar-libraries ${seastar-libraries} PARENT_SCOPE) +endfunction () + # We set the following environment variables # * ASAN_OPTIONS=disable_coredump=0:abort_on_error=1:detect_stack_use_after_return=1:verify_asan_link_order=0 # By default ASan disables core dumps because they used to be @@ -505,7 +560,7 @@ seastar_generate_protobuf ( IN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/proto/metrics2.proto OUT_DIR ${Seastar_GEN_BINARY_DIR}/src/proto) -add_library (seastar +add_library (seastar-objects OBJECT ${http_chunk_parsers_file} ${http_request_parser_file} ${proto_metrics2_files} @@ -784,15 +839,13 @@ add_library (seastar set_source_files_properties(src/core/thread.cc PROPERTIES COMPILE_FLAGS -U_FORTIFY_SOURCE) -add_library (Seastar::seastar ALIAS seastar) - -add_dependencies (seastar +add_dependencies (seastar-objects seastar_http_chunk_parsers seastar_http_request_parser seastar_http_response_parser seastar_proto_metrics2) -target_include_directories (seastar +target_include_directories (seastar-objects PUBLIC $ $ @@ -824,12 +877,12 @@ endif () if (CMAKE_CXX_STANDARD GREATER_EQUAL 23) include (CheckP2582R1) if (Cxx_Compiler_IMPLEMENTS_P2581R1) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_P2581R1) endif () endif () -if (BUILD_SHARED_LIBS) +if (BUILD_SHARED_LIBS OR Seastar_BUILD_SHARED_LIBS) # use initial-exec TLS, as it puts the TLS variables in the static TLS space # instead of allocating them using malloc. otherwise intercepting mallocs and # friends could lead to recursive call of malloc functions when a dlopen'ed @@ -848,7 +901,7 @@ if (Seastar_COMPRESS_DEBUG) list (APPEND Seastar_PRIVATE_CXX_FLAGS -gz) endif () -target_link_libraries (seastar +target_link_libraries (seastar-objects PUBLIC Boost::boost Boost::program_options @@ -868,17 +921,17 @@ target_link_libraries (seastar yaml-cpp::yaml-cpp Threads::Threads) if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.26) - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE "$") else () - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE "$") endif () if (Seastar_DPDK) - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE DPDK::dpdk) endif () @@ -892,7 +945,7 @@ if (condition) message (FATAL_ERROR "Sanitizers not found!") endif () set (Seastar_Sanitizers_OPTIONS ${Sanitizers_COMPILE_OPTIONS}) - target_link_libraries (seastar + target_link_libraries (seastar-objects PUBLIC $<${condition}:Sanitizers::address> $<${condition}:Sanitizers::undefined_behavior>) @@ -913,19 +966,19 @@ include (CTest) # To disable -Werror, pass -Wno-error to Seastar_CXX_FLAGS. # -target_compile_definitions(seastar +target_compile_definitions(seastar-objects PUBLIC SEASTAR_API_LEVEL=${Seastar_API_LEVEL} $<$:SEASTAR_BUILD_SHARED_LIBS>) -target_compile_features(seastar +target_compile_features(seastar-objects PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) include (CheckCXXCompilerFlag) check_cxx_compiler_flag ("-Wno-maybe-uninitialized -Werror" MaybeUninitialized_FOUND) if (MaybeUninitialized_FOUND) - target_compile_options (seastar + target_compile_options (seastar-objects PUBLIC # With std::experimental::optional it is easy to hit # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88897. We disable @@ -935,19 +988,19 @@ if (MaybeUninitialized_FOUND) endif () if (Seastar_SSTRING) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_SSTRING) endif () if (Seastar_DEPRECATED_OSTREAM_FORMATTERS) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_DEPRECATED_OSTREAM_FORMATTERS) endif () if (LinuxMembarrier_FOUND) list (APPEND Seastar_PRIVATE_COMPILE_DEFINITIONS SEASTAR_HAS_MEMBARRIER) - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE LinuxMembarrier::membarrier) endif () @@ -955,17 +1008,17 @@ tri_state_option (${Seastar_ALLOC_FAILURE_INJECTION} DEFAULT_BUILD_TYPES "Dev" CONDITION condition) if (condition) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC $<${condition}:SEASTAR_ENABLE_ALLOC_FAILURE_INJECTION>) endif () if (Seastar_TASK_BACKTRACE) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_TASK_BACKTRACE) endif () if (Seastar_DEBUG_ALLOCATIONS) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PRIVATE SEASTAR_DEBUG_ALLOCATIONS) endif () @@ -974,16 +1027,16 @@ if (Sanitizers_FIBER_SUPPORT) endif () if (Seastar_ALLOC_PAGE_SIZE) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_OVERRIDE_ALLOCATOR_PAGE_SIZE=${Seastar_ALLOC_PAGE_SIZE}) endif () if (Seastar_LOGGER_COMPILE_TIME_FMT) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_LOGGER_COMPILE_TIME_FMT) endif () -target_compile_definitions (seastar +target_compile_definitions (seastar-objects PUBLIC SEASTAR_SCHEDULING_GROUPS_COUNT=${Seastar_SCHEDULING_GROUPS_COUNT}) if (Seastar_CXX_FLAGS) @@ -997,9 +1050,9 @@ endif () # with them and some client code without. if (Seastar_SPLIT_DWARF) set (Seastar_SPLIT_DWARF_FLAG "-Wl,--gdb-index") - target_link_libraries (seastar PUBLIC + target_link_libraries (seastar-objects PUBLIC $<$>:${Seastar_SPLIT_DWARF_FLAG}>) - target_compile_options (seastar PUBLIC + target_compile_options (seastar-objects PUBLIC $<$>:-gsplit-dwarf>) endif () @@ -1020,66 +1073,66 @@ endif () if (Seastar_DPDK) if (CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64") - target_compile_options (seastar + target_compile_options (seastar-objects PUBLIC -mcpu=${Seastar_DPDK_MACHINE} -mtune=${Seastar_DPDK_MACHINE}) else() - target_compile_options (seastar + target_compile_options (seastar-objects PUBLIC -march=${Seastar_DPDK_MACHINE}) endif () - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_HAVE_DPDK) endif () if (Seastar_HWLOC) list (APPEND Seastar_PRIVATE_COMPILE_DEFINITIONS SEASTAR_HAVE_HWLOC) - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE hwloc::hwloc) endif () set_option_if_package_is_found (Seastar_IO_URING LibUring) if (Seastar_IO_URING) list (APPEND Seastar_PRIVATE_COMPILE_DEFINITIONS SEASTAR_HAVE_URING) - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE URING::uring) endif () if (Seastar_LD_FLAGS) - target_link_options (seastar + target_link_options (seastar-objects PRIVATE ${Seastar_LD_FLAGS}) endif () if (Seastar_NUMA) list (APPEND Seastar_PRIVATE_COMPILE_DEFINITIONS SEASTAR_HAVE_NUMA) - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE numactl::numactl) endif () if (SystemTap-SDT_FOUND) list (APPEND Seastar_PRIVATE_COMPILE_DEFINITIONS SEASTAR_HAVE_SYSTEMTAP_SDT) - target_link_libraries (seastar + target_link_libraries (seastar-objects PRIVATE SystemTap::SDT) endif () check_cxx_compiler_flag ("-Werror=unused-result" ErrorUnused_FOUND) if (ErrorUnused_FOUND) if (Seastar_UNUSED_RESULT_ERROR) - target_compile_options (seastar + target_compile_options (seastar-objects PUBLIC -Werror=unused-result) else() - target_compile_options (seastar + target_compile_options (seastar-objects PUBLIC -Wno-error=unused-result) endif () endif () check_cxx_compiler_flag ("-Wno-error=#warnings" ErrorWarnings_FOUND) if (ErrorWarnings_FOUND) - target_compile_options (seastar + target_compile_options (seastar-objects PRIVATE "-Wno-error=#warnings") endif () @@ -1087,7 +1140,7 @@ foreach (definition SEASTAR_DEBUG SEASTAR_DEFAULT_ALLOCATOR SEASTAR_SHUFFLE_TASK_QUEUE) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC $<$,Debug;Sanitize>:${definition}>) endforeach () @@ -1096,7 +1149,7 @@ tri_state_option (${Seastar_DEBUG_SHARED_PTR} DEFAULT_BUILD_TYPES "Debug" "Sanitize" CONDITION condition) if (condition) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC $<${condition}:SEASTAR_DEBUG_SHARED_PTR>) endif () @@ -1105,7 +1158,7 @@ tri_state_option (${Seastar_DEBUG_SHARED_PTR} DEFAULT_BUILD_TYPES "Debug" "Sanitize" CONDITION condition) if (condition) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC $<${condition}:SEASTAR_DEBUG_PROMISE>) endif () @@ -1120,30 +1173,32 @@ if (condition) # otherwise clang can soft-fail (return 0 but emit a warning) instead. check_cxx_compiler_flag ("-fstack-clash-protection -Werror" StackClashProtection_FOUND) if (StackClashProtection_FOUND) - target_compile_options (seastar + target_compile_options (seastar-objects PUBLIC $<${condition}:-fstack-clash-protection>) endif () - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PRIVATE $<${condition}:SEASTAR_THREAD_STACK_GUARDS>) endif () -target_compile_definitions (seastar +target_compile_definitions (seastar-objects PUBLIC $<$,Dev;Debug>:SEASTAR_TYPE_ERASE_MORE>) -target_compile_definitions (seastar +target_compile_definitions (seastar-objects PRIVATE ${Seastar_PRIVATE_COMPILE_DEFINITIONS}) -target_compile_options (seastar +target_compile_options (seastar-objects PRIVATE ${Seastar_PRIVATE_CXX_FLAGS}) -set_target_properties (seastar +set_target_properties (seastar-objects PROPERTIES CXX_STANDARD ${CMAKE_CXX_STANDARD} CXX_EXTENSIONS ON) +seastar_add_library (seastar seastar-objects) + add_library (seastar_private INTERFACE) target_compile_definitions (seastar_private @@ -1160,7 +1215,7 @@ target_link_libraries (seastar_private # if (Seastar_INSTALL OR Seastar_TESTING) - add_library (seastar_testing + add_library (seastar_testing-objects OBJECT include/seastar/testing/entry_point.hh include/seastar/testing/exchanger.hh include/seastar/testing/random.hh @@ -1173,34 +1228,35 @@ if (Seastar_INSTALL OR Seastar_TESTING) src/testing/seastar_test.cc src/testing/test_runner.cc) - add_library (Seastar::seastar_testing ALIAS seastar_testing) - - target_compile_definitions (seastar_testing + target_compile_definitions (seastar_testing-objects PRIVATE ${Seastar_PRIVATE_COMPILE_DEFINITIONS}) - target_compile_options (seastar_testing + target_compile_options (seastar_testing-objects PRIVATE ${Seastar_PRIVATE_CXX_FLAGS}) - target_link_libraries (seastar_testing + target_link_libraries (seastar_testing-objects PUBLIC Boost::unit_test_framework Boost::dynamic_linking seastar) - add_library(seastar_perf_testing + seastar_add_library (seastar_testing seastar_testing-objects) + + add_library(seastar_perf_testing-objects OBJECT src/testing/random.cc include/seastar/testing/perf_tests.hh tests/perf/perf_tests.cc tests/perf/linux_perf_event.cc) - add_library (Seastar::seastar_perf_testing ALIAS seastar_perf_testing) - target_compile_definitions (seastar_perf_testing + + target_compile_definitions (seastar_perf_testing-objects PRIVATE ${Seastar_PRIVATE_COMPILE_DEFINITIONS}) - target_compile_options (seastar_perf_testing + target_compile_options (seastar_perf_testing-objects PRIVATE ${Seastar_PRIVATE_CXX_FLAGS}) - target_link_libraries (seastar_perf_testing + target_link_libraries (seastar_perf_testing-objects PUBLIC seastar) + seastar_add_library (seastar_perf_testing seastar_perf_testing-objects) endif () if (Seastar_MODULE) @@ -1369,9 +1425,7 @@ if (Seastar_INSTALL) install ( TARGETS - seastar - seastar_testing - seastar_perf_testing + ${seastar-libraries} EXPORT seastar-export LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/cmake/CheckLibc.cmake b/cmake/CheckLibc.cmake index b8b0cf6d779..94bec1a989e 100644 --- a/cmake/CheckLibc.cmake +++ b/cmake/CheckLibc.cmake @@ -8,7 +8,7 @@ if (Stdout_Can_Be_Used_As_Identifier) # "stdout" is defined as a macro by the C++ standard, so we cannot assume # that the macro is always expanded into an identifier which can be re-used # to name a enumerator in the declaration of an enumeration. - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PUBLIC SEASTAR_LOGGER_TYPE_STDOUT) endif () @@ -25,7 +25,7 @@ int main() { if (Strerror_R_Returns_Char_P) # define SEASTAR_STRERROR_R_CHAR_P if strerror_r() is GNU-specific version, # which returns a "char*" not "int". - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PRIVATE SEASTAR_STRERROR_R_CHAR_P) endif () @@ -35,7 +35,7 @@ include (CheckFunctionExists) check_function_exists (pthread_attr_setaffinity_np Pthread_Attr_Setaffinity_Np) if (Pthread_Attr_Setaffinity_Np) - target_compile_definitions (seastar + target_compile_definitions (seastar-objects PRIVATE SEASTAR_PTHREAD_ATTR_SETAFFINITY_NP) endif () diff --git a/cmake/SeastarConfig.cmake.in b/cmake/SeastarConfig.cmake.in index 9fc8bd3de8f..bd117fc7992 100644 --- a/cmake/SeastarConfig.cmake.in +++ b/cmake/SeastarConfig.cmake.in @@ -32,6 +32,21 @@ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) include (SeastarDependencies) seastar_find_dependencies () -if (NOT TARGET Seastar::seastar) +if (NOT (TARGET Seastar::seastar-static OR TARGET Seastar::seastar-shared)) include ("${CMAKE_CURRENT_LIST_DIR}/SeastarTargets.cmake") endif () + +# make sure libraries like Seastar::seastar always exist +foreach (component seastar seastar_testing seastar_perf_testing) + if (TARGET Seastar::${component}) + continue () + endif () + + # prefer static libraries over the shared ones + foreach (type static shared) + if (TARGET Seastar::${component}-${type}) + add_library (Seastar::${component} ALIAS Seastar::${component}-${type}) + break () + endif () + endforeach () +endforeach ()