From 730e13050142f7140a8b3de85b2a2b164eb1bc0e Mon Sep 17 00:00:00 2001 From: Tristan Stenner Date: Fri, 4 Jun 2021 17:17:18 +0200 Subject: [PATCH 1/3] CMake: clean up CMake config, link object files privately to avoid exporting the lslobj and lslboost targets --- CMakeLists.txt | 103 +++++++++++++++++++++-------------------- testing/CMakeLists.txt | 3 +- 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d4792ca5..8304c4ce8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden) if(NOT MSVC_VERSION VERSION_LESS 1700) set(CMAKE_CXX_STANDARD 14) endif() +# generate a compilation database (compile_commands.json) for clang tooling set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(LSL_LIB_TYPE SHARED) option(LSL_DEBUGLOG "Enable (lots of) additional debug messages" OFF) option(LSL_UNIXFOLDERS "Use the unix folder layout for install targets" On) @@ -28,6 +28,8 @@ set(LSL_WINVER "0x0601" CACHE STRING if(LSL_BUILD_STATIC) set(LSL_LIB_TYPE STATIC) else() + set(LSL_LIB_TYPE SHARED) + # shared libraries require relocatable symbols so we enable them by default set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif() @@ -106,7 +108,7 @@ if(LSL_BUNDLED_PUGIXML) message(STATUS "Using bundled pugixml") target_sources(lslobj PRIVATE thirdparty/pugixml/pugixml.cpp) target_include_directories(lslobj SYSTEM PUBLIC - $) + ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/pugixml) else() message(STATUS "Using system pugixml") find_package(pugixml REQUIRED) @@ -138,34 +140,25 @@ else() set(lslgitrevision "unknown") set(lslgitbranch "unknown") endif() + +# generate a version information string that can be retrieved with the exported +# lsl_library_info() function set(LSL_VERSION_INFO "git:${lslgitrevision}/branch:${lslgitbranch}/build:${CMAKE_BUILD_TYPE}/compiler:${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}") +set_source_files_properties("src/buildinfo.cpp" + PROPERTIES COMPILE_DEFINITIONS + LSL_LIBRARY_INFO_STR="${LSL_VERSION_INFO}/link:${LSL_LIB_TYPE}" +) set_source_files_properties("thirdparty/loguru/loguru.cpp" PROPERTIES COMPILE_DEFINITIONS LOGURU_STACKTRACES=$) -## create the lslboost target +find_package(Threads REQUIRED) + +# create the lslboost target add_library(lslboost OBJECT lslboost/asio_objects.cpp lslboost/serialization_objects.cpp ) - -if(UNIX) - include(CheckSymbolExists) - # look for clock_gettime, if not we need to link against librt - check_symbol_exists(clock_gettime time.h HAS_GETTIME) - if(NOT HAS_GETTIME) - set(NEEDS_LIBRT ON CACHE INTERNAL "Link to librt") - endif() -endif() - -find_package(Threads REQUIRED) -target_link_libraries(lslboost - PUBLIC - Threads::Threads - PRIVATE - $<$:bcrypt> - $<$:mswsock> - $<$:ws2_32> - ) +target_link_libraries(lslboost PUBLIC Threads::Threads) target_compile_features(lslboost PUBLIC cxx_std_11 cxx_lambda_init_captures) target_compile_definitions(lslboost @@ -174,50 +167,62 @@ target_compile_definitions(lslboost BOOST_ASIO_STANDALONE BOOST_ASIO_SEPARATE_COMPILATION BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS - $<$:_WIN32_WINNT=${LSL_WINVER}> - PRIVATE - $<$:BOOST_THREAD_BUILD_DLL> ) target_include_directories(lslboost SYSTEM PUBLIC - $) - + ${CMAKE_CURRENT_SOURCE_DIR}/lslboost) -target_link_libraries(lslobj - PRIVATE - lslboost - $<$:iphlpapi> - $<$:winmm> - PUBLIC - $<$,$>:dl> - $<$:rt> - ) +# target configuration for the internal lslobj target +target_link_libraries(lslobj PRIVATE lslboost) target_include_directories(lslobj PUBLIC $ ) target_include_directories(lslobj SYSTEM PUBLIC $ ) -target_compile_definitions(lslobj - PRIVATE LIBLSL_EXPORTS $<$:_CRT_SECURE_NO_WARNINGS> - LOGURU_DEBUG_LOGGING=$ - INTERFACE LSLNOAUTOLINK # don't use #pragma(lib) in CMake builds +target_compile_definitions(lslobj PRIVATE + LIBLSL_EXPORTS + LOGURU_DEBUG_LOGGING=$ ) +# platform specific configuration +if(UNIX) + include(CheckSymbolExists) + # check that clock_gettime is present in the stdlib, link against librt otherwise + check_symbol_exists(clock_gettime time.h HAS_GETTIME) + if(NOT HAS_GETTIME) + target_link_libraries(lslobj PRIVATE rt) + endif() + if(LSL_DEBUGLOG AND NOT APPLE) + target_link_libraries(lslobj PRIVATE dl) + endif() +elseif(WIN32) + target_link_libraries(lslobj PRIVATE iphlpapi winmm) + target_link_libraries(lslboost PRIVATE bcrypt mswsock ws2_32) + target_compile_definitions(lslobj + PRIVATE _CRT_SECURE_NO_WARNINGS + PUBLIC LSLNOAUTOLINK # don't use #pragma(lib) in CMake builds + ) + target_compile_definitions(lslboost + PUBLIC _WIN32_WINNT=${LSL_WINVER} + PRIVATE BOOST_THREAD_BUILD_DLL + ) +endif() + +# the "real" liblsl library. It contains one source with the version info +# string because some generators require it. The remaining source code is +# built in the lslobj target and later linked into this library add_library(lsl ${LSL_LIB_TYPE} src/buildinfo.cpp) # defines for LSL_CPP_API export header (shared: dllimport/dllexport) target_compile_definitions(lsl PUBLIC $,LIBLSL_STATIC,LIBLSL_EXPORTS> + $<$:LSLNOAUTOLINK> # don't use #pragma(lib) in CMake builds ) - -set_source_files_properties("src/buildinfo.cpp" - PROPERTIES COMPILE_DEFINITIONS - LSL_LIBRARY_INFO_STR="${LSL_VERSION_INFO}/link:${LSL_LIB_TYPE}" +target_link_libraries(lsl PRIVATE lslobj lslboost) +target_include_directories(lsl INTERFACE + $ + $ ) - -target_link_libraries(lsl - PUBLIC lslobj - PRIVATE lslboost) set_target_properties(lsl PROPERTIES VERSION ${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH} ) @@ -246,7 +251,7 @@ write_basic_package_version_file( COMPATIBILITY AnyNewerVersion ) -install(TARGETS lsl lslobj lslboost +install(TARGETS lsl EXPORT LSLTargets COMPONENT liblsl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index d3ed4f7dc..ae970d67a 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -25,7 +25,8 @@ add_executable(lsl_test_exported test_ext_streaminfo.cpp test_ext_time.cpp ) -target_link_libraries(lsl_test_exported PRIVATE lsl catch_main) + +target_link_libraries(lsl_test_exported PRIVATE lsl catch_main Threads::Threads) find_package(Threads REQUIRED) From 2a2daefa2154cdebfe122d9cfcbd563f118b01c7 Mon Sep 17 00:00:00 2001 From: Tristan Stenner Date: Tue, 8 Jun 2021 11:17:04 +0200 Subject: [PATCH 2/3] CMake: allow the compiler to hide functions marked as inline --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8304c4ce8..7f6aaf0eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ project (liblsl ) set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) if(NOT MSVC_VERSION VERSION_LESS 1700) set(CMAKE_CXX_STANDARD 14) endif() From 377338155f260faf492d19295cfda9bfd956b1a4 Mon Sep 17 00:00:00 2001 From: Tristan Stenner Date: Tue, 8 Jun 2021 11:20:00 +0200 Subject: [PATCH 3/3] CMake: add LSL_OPTIMIZATIONS option; enables LTO & disables pre-building all of Asio --- CMakeLists.txt | 16 ++++++++++++++-- examples/CMakeLists.txt | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f6aaf0eb..1c24793e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ option(LSL_FORCE_FANCY_LIBNAME "Add library name decorations (32/64/-debug)" OFF option(LSL_BUILD_EXAMPLES "Build example programs in examples/" OFF) option(LSL_BUILD_STATIC "Build LSL as static library." OFF) option(LSL_LEGACY_CPP_ABI "Build legacy C++ ABI into lsl-static" OFF) +option(LSL_OPTIMIZATIONS "Enable some more compiler optimizations" ON) option(LSL_UNITTESTS "Build LSL library unit tests" OFF) option(LSL_BUNDLED_PUGIXML "Use the bundled pugixml by default" ON) @@ -156,7 +157,6 @@ find_package(Threads REQUIRED) # create the lslboost target add_library(lslboost OBJECT - lslboost/asio_objects.cpp lslboost/serialization_objects.cpp ) target_link_libraries(lslboost PUBLIC Threads::Threads) @@ -166,7 +166,6 @@ target_compile_definitions(lslboost PUBLIC BOOST_ALL_NO_LIB BOOST_ASIO_STANDALONE - BOOST_ASIO_SEPARATE_COMPILATION BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS ) target_include_directories(lslboost SYSTEM PUBLIC @@ -228,6 +227,19 @@ set_target_properties(lsl PROPERTIES VERSION ${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH} ) +# enable some additional expensive compiler optimizations +if(LSL_OPTIMIZATIONS) + # enable LTO (https://en.wikipedia.org/wiki/Interprocedural_optimization + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +else() + # build one object file for Asio instead of once every time an Asio function is called. See + # https://think-async.com/Asio/asio-1.18.2/doc/asio/using.html#asio.using.optional_separate_compilation + target_sources(lslboost PRIVATE lslboost/asio_objects.cpp) + target_compile_definitions(lslboost PUBLIC BOOST_ASIO_SEPARATE_COMPILATION) +endif() + + + if(LSL_FORCE_FANCY_LIBNAME) math(EXPR lslplatform "8 * ${CMAKE_SIZEOF_VOID_P}") set_target_properties(lsl PROPERTIES diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 64dafefe9..433add672 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.12) project(lslexamples LANGUAGES C CXX VERSION 0.2.0)