From 2e98feebc0c25ea8fb634a651eeeec2ef2cd86c7 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 13:23:01 -0400 Subject: [PATCH 1/9] Refactor CMake to make it easier to follow by modularizing concerns --- CMakeLists.txt | 346 ++--------------------------------- cmake/CompilerSettings.cmake | 35 ++++ cmake/Dependencies.cmake | 36 ++++ cmake/GitVersion.cmake | 26 +++ cmake/Installation.cmake | 83 +++++++++ cmake/ProjectOptions.cmake | 13 ++ cmake/SourceFiles.cmake | 82 +++++++++ cmake/TargetLib.cmake | 45 +++++ cmake/TargetObjLib.cmake | 89 +++++++++ cmake/TargetOther.cmake | 11 ++ 10 files changed, 435 insertions(+), 331 deletions(-) create mode 100644 cmake/CompilerSettings.cmake create mode 100644 cmake/Dependencies.cmake create mode 100644 cmake/GitVersion.cmake create mode 100644 cmake/Installation.cmake create mode 100644 cmake/ProjectOptions.cmake create mode 100644 cmake/SourceFiles.cmake create mode 100644 cmake/TargetLib.cmake create mode 100644 cmake/TargetObjLib.cmake create mode 100644 cmake/TargetOther.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f86958f7..98904a83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,349 +4,33 @@ project (liblsl LANGUAGES C CXX DESCRIPTION "Labstreaminglayer C/C++ library" HOMEPAGE_URL "https://github.com/sccn/liblsl" - ) +) # API version, to be incremented on backwards-incompatible ABI changes set(LSL_ABI_VERSION 2) -set(CMAKE_CXX_VISIBILITY_PRESET hidden) -set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) - set(CMAKE_CXX_STANDARD 17) -# generate a compilation database (compile_commands.json) for clang tooling -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -option(LSL_DEBUGLOG "Enable (lots of) additional debug messages" OFF) -option(LSL_UNIXFOLDERS "Use the unix folder layout for install targets" On) -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_BOOST "Use the bundled Boost by default" ON) -option(LSL_BUNDLED_PUGIXML "Use the bundled pugixml by default" ON) -option(LSL_TOOLS "Build some experimental tools for in-depth tests" OFF) - -mark_as_advanced(LSL_FORCE_FANCY_LIBNAME) - -set(LSL_WINVER "0x0601" CACHE STRING - "Windows version (_WIN32_WINNT) to target (defaults to 0x0601 for Windows 7)") - -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() - -# Add an object library so all files are only compiled once -add_library(lslobj OBJECT - src/api_config.cpp - src/api_config.h - src/api_types.hpp - src/cancellable_streambuf.h - src/cancellation.h - src/cancellation.cpp - src/common.cpp - src/common.h - src/consumer_queue.cpp - src/consumer_queue.h - src/data_receiver.cpp - src/data_receiver.h - src/forward.h - src/info_receiver.cpp - src/info_receiver.h - src/inlet_connection.cpp - src/inlet_connection.h - src/lsl_resolver_c.cpp - src/lsl_inlet_c.cpp - src/lsl_outlet_c.cpp - src/lsl_streaminfo_c.cpp - src/lsl_xml_element_c.cpp - src/netinterfaces.h - src/netinterfaces.cpp - src/portable_archive/portable_archive_exception.hpp - src/portable_archive/portable_archive_includes.hpp - src/portable_archive/portable_iarchive.hpp - src/portable_archive/portable_oarchive.hpp - src/resolver_impl.cpp - src/resolver_impl.h - src/resolve_attempt_udp.cpp - src/resolve_attempt_udp.h - src/sample.cpp - src/sample.h - src/send_buffer.cpp - src/send_buffer.h - src/socket_utils.cpp - src/socket_utils.h - src/stream_info_impl.cpp - src/stream_info_impl.h - src/stream_inlet_impl.h - src/stream_outlet_impl.cpp - src/stream_outlet_impl.h - src/tcp_server.cpp - src/tcp_server.h - src/time_postprocessor.cpp - src/time_postprocessor.h - src/time_receiver.cpp - src/time_receiver.h - src/udp_server.cpp - src/udp_server.h - src/util/cast.hpp - src/util/cast.cpp - src/util/endian.cpp - src/util/endian.hpp - src/util/inireader.hpp - src/util/inireader.cpp - src/util/strfuns.hpp - src/util/strfuns.cpp - src/util/uuid.hpp - thirdparty/loguru/loguru.cpp - $<$:src/legacy/legacy_abi.cpp src/legacy/legacy_abi.h> - # headers - include/lsl_c.h - include/lsl_cpp.h - include/lsl/common.h - include/lsl/inlet.h - include/lsl/outlet.h - include/lsl/resolver.h - include/lsl/streaminfo.h - include/lsl/types.h - include/lsl/xml.h -) - -if(LSL_BUNDLED_PUGIXML) - message(STATUS "Using bundled pugixml") - target_sources(lslobj PRIVATE thirdparty/pugixml/pugixml.cpp) - target_include_directories(lslobj SYSTEM PUBLIC - $) -else() - message(STATUS "Using system pugixml") - find_package(pugixml REQUIRED) - if(NOT TARGET pugixml::pugixml) - add_library(pugixml::pugixml ALIAS pugixml) - endif() - target_link_libraries(lslobj PUBLIC pugixml::pugixml) -endif() - -# try to find out which revision is currently checked out -find_package(Git) -if(lslgitrevision AND lslgitbranch) - message(STATUS "Got git information ${lslgitrevision}/${lslgitbranch} from the command line") -elseif(GIT_FOUND) - execute_process( - COMMAND ${GIT_EXECUTABLE} describe --tags HEAD - WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" - OUTPUT_VARIABLE lslgitrevision - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( - COMMAND ${GIT_EXECUTABLE} rev-parse --symbolic-full-name --abbrev-ref @ - WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" - OUTPUT_VARIABLE lslgitbranch - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - message(STATUS "Git version information: ${lslgitbranch}/${lslgitrevision}") -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=$) - -find_package(Threads REQUIRED) - -# create the lslboost target -add_library(lslboost INTERFACE) -if(LSL_BUNDLED_BOOST) - message(STATUS "Using bundled Boost") - target_include_directories(lslboost SYSTEM INTERFACE - $) -else() - message(STATUS "Using system Boost") - find_package(Boost REQUIRED) - target_compile_definitions(lslboost - INTERFACE - lslboost=boost # allows the LSL code base to work with the original Boost namespace/headers - ) - target_link_libraries(lslboost INTERFACE Boost::boost Boost::disable_autolinking) -endif() - -target_compile_definitions(lslboost INTERFACE BOOST_ALL_NO_LIB) - -# target configuration for the internal lslobj target -target_link_libraries(lslobj PRIVATE lslboost Threads::Threads) -target_compile_features(lslobj PUBLIC cxx_std_17) -target_include_directories(lslobj - PUBLIC - $ - $ - INTERFACE # for unit tests - $ - ) -target_include_directories(lslobj - SYSTEM PUBLIC - $ - $ -) -target_compile_definitions(lslobj PRIVATE - LIBLSL_EXPORTS - LOGURU_DEBUG_LOGGING=$ - PUBLIC ASIO_NO_DEPRECATED -) -if(MINGW) - target_link_libraries(lslobj PRIVATE bcrypt) -endif() - -# platform specific configuration -if(UNIX AND NOT APPLE) - 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) - target_link_libraries(lslobj PRIVATE dl) - endif() -elseif(WIN32) - target_link_libraries(lslobj PRIVATE iphlpapi winmm mswsock ws2_32) - target_compile_definitions(lslobj - PRIVATE _CRT_SECURE_NO_WARNINGS - PUBLIC LSLNOAUTOLINK # don't use #pragma(lib) in CMake builds - _WIN32_WINNT=${LSL_WINVER} - ) -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 -) -target_link_libraries(lsl PRIVATE lslobj lslboost) -target_include_directories(lsl INTERFACE - $ - $ -) -set_target_properties(lsl PROPERTIES - VERSION ${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH} - SOVERSION ${LSL_ABI_VERSION} -) - -# 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(lslobj PRIVATE thirdparty/asio_objects.cpp) - target_compile_definitions(lslobj PUBLIC ASIO_SEPARATE_COMPILATION ASIO_DISABLE_VISIBILITY) -endif() - - - -if(LSL_FORCE_FANCY_LIBNAME) - math(EXPR lslplatform "8 * ${CMAKE_SIZEOF_VOID_P}") - set_target_properties(lsl PROPERTIES - PREFIX "" - OUTPUT_NAME "liblsl${lslplatform}" - DEBUG_POSTFIX "-debug" - ) -endif() - -if(LSL_UNIXFOLDERS) - include(GNUInstallDirs) -else() - set(CMAKE_INSTALL_BINDIR LSL) - set(CMAKE_INSTALL_LIBDIR LSL) - set(CMAKE_INSTALL_INCLUDEDIR LSL/include) -endif() - -include(CMakePackageConfigHelpers) -write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/LSLConfigVersion.cmake" - VERSION "${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH}" - COMPATIBILITY AnyNewerVersion -) - -set(LSLTargets lsl) -if(LSL_BUILD_STATIC) - list(APPEND LSLTargets lslobj lslboost) -endif() - -install(TARGETS ${LSLTargets} - EXPORT LSLTargets - COMPONENT liblsl - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) - -export(EXPORT LSLTargets - FILE "${CMAKE_CURRENT_BINARY_DIR}/LSLTargets.cmake" - NAMESPACE LSL:: -) - -install(EXPORT LSLTargets - FILE LSLTargets.cmake - COMPONENT liblsl - NAMESPACE "LSL::" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL -) -configure_file(cmake/LSLConfig.cmake "${CMAKE_CURRENT_BINARY_DIR}/LSLConfig.cmake" COPYONLY) -configure_file(cmake/LSLCMake.cmake "${CMAKE_CURRENT_BINARY_DIR}/LSLCMake.cmake" COPYONLY) - - -# install headers -install(DIRECTORY include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - COMPONENT liblsl -) - -install(FILES - cmake/LSLCMake.cmake - ${CMAKE_CURRENT_BINARY_DIR}/LSLConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/LSLConfigVersion.cmake - COMPONENT liblsl - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL -) - +# Include modular configuration files +include(cmake/ProjectOptions.cmake) # +include(cmake/CompilerSettings.cmake) # +include(cmake/Dependencies.cmake) # +include(cmake/SourceFiles.cmake) # +include(cmake/TargetObjLib.cmake) # +include(cmake/TargetLib.cmake) # +include(cmake/Installation.cmake) # include(cmake/LSLCMake.cmake) +include(cmake/TargetOther.cmake) -add_executable(lslver testing/lslver.c) -target_link_libraries(lslver PRIVATE lsl) -installLSLApp(lslver) - -if(NOT WIN32 AND LSL_TOOLS) - add_executable(blackhole testing/blackhole.cpp) - target_link_libraries(blackhole PRIVATE Threads::Threads) - target_include_directories(blackhole PRIVATE "thirdparty/asio/") - installLSLApp(blackhole) -endif() - -set(LSL_INSTALL_ROOT ${CMAKE_CURRENT_BINARY_DIR}) if(LSL_UNITTESTS) add_subdirectory(testing) endif() if(LSL_BUILD_EXAMPLES) + set(LSL_INSTALL_ROOT ${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(examples) endif() +# Config for packaging +# TODO: Config for packaging for the library itself is likely to diverge from config for packing applications. e.g., +# -> Optionally install to system directories +# -> Apple Framework -- different installer type; uses entitlements LSLGenerateCPackConfig() diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake new file mode 100644 index 00000000..c43872b0 --- /dev/null +++ b/cmake/CompilerSettings.cmake @@ -0,0 +1,35 @@ +# Compiler and language settings +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) +# generate a compilation database (compile_commands.json) for clang tooling +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Enable position independent code for shared libraries +if(NOT LSL_BUILD_STATIC OR UNIX) + # shared libraries require relocatable symbols so we enable them by default + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + +# Determine library type +if(LSL_BUILD_STATIC) + set(LSL_LIB_TYPE STATIC) +else() + set(LSL_LIB_TYPE SHARED) +endif() + +# Enable optimizations if requested +if(LSL_OPTIMIZATIONS) + # enable LTO (https://en.wikipedia.org/wiki/Interprocedural_optimization + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +endif() + +# Platform-specific settings +if(WIN32) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + set(LSL_WINVER "0x0601" CACHE STRING + "Windows version (_WIN32_WINNT) to target (defaults to 0x0601 for Windows 7)") +elseif(APPLE) + set(CMAKE_MACOSX_RPATH ON) +endif() diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake new file mode 100644 index 00000000..fd3e4404 --- /dev/null +++ b/cmake/Dependencies.cmake @@ -0,0 +1,36 @@ +find_package(Threads REQUIRED) + +# Git version information +include(cmake/GitVersion.cmake) + +# PugiXML dependency +if(LSL_BUNDLED_PUGIXML) + message(STATUS "Using bundled pugixml") + # We will later add the pugixml source files to the lslobj target +else() + message(STATUS "Using system pugixml") + find_package(pugixml REQUIRED) + if(NOT TARGET pugixml::pugixml) + add_library(pugixml::pugixml ALIAS pugixml) + endif() +endif() + +# Create lslboost target +add_library(lslboost INTERFACE) +if(LSL_BUNDLED_BOOST) + message(STATUS "Using bundled header-only Boost") + target_include_directories(lslboost SYSTEM INTERFACE + $) +else() + message(STATUS "Using system Boost") + find_package(Boost REQUIRED) + target_compile_definitions(lslboost INTERFACE + lslboost=boost # allows the LSL code base to work with the original Boost namespace/headers + ) + target_link_libraries(lslboost INTERFACE Boost::boost Boost::disable_autolinking) +endif() +target_compile_definitions(lslboost INTERFACE BOOST_ALL_NO_LIB) + +# Enable LOGURU stack traces if LSL_DEBUGLOG is enabled. +set_source_files_properties("thirdparty/loguru/loguru.cpp" + PROPERTIES COMPILE_DEFINITIONS LOGURU_STACKTRACES=$) diff --git a/cmake/GitVersion.cmake b/cmake/GitVersion.cmake new file mode 100644 index 00000000..fde2a0c2 --- /dev/null +++ b/cmake/GitVersion.cmake @@ -0,0 +1,26 @@ +# Try to find out which revision is currently checked out +find_package(Git) +if(lslgitrevision AND lslgitbranch) + message(STATUS "Got git information ${lslgitrevision}/${lslgitbranch} from the command line") +elseif(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --tags HEAD + WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" + OUTPUT_VARIABLE lslgitrevision + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --symbolic-full-name --abbrev-ref @ + WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" + OUTPUT_VARIABLE lslgitbranch + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + message(STATUS "Git version information: ${lslgitbranch}/${lslgitrevision}") +else() + set(lslgitrevision "unknown") + set(lslgitbranch "unknown") +endif() + +# Generate 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}") diff --git a/cmake/Installation.cmake b/cmake/Installation.cmake new file mode 100644 index 00000000..72703c28 --- /dev/null +++ b/cmake/Installation.cmake @@ -0,0 +1,83 @@ +# Configure installation + +# Paths +if(LSL_UNIXFOLDERS) + include(GNUInstallDirs) +else() + set(CMAKE_INSTALL_BINDIR LSL) + set(CMAKE_INSTALL_LIBDIR LSL) + set(CMAKE_INSTALL_INCLUDEDIR LSL/include) +endif() + +# Define installation targets +set(LSLTargets lsl) +if(LSL_BUILD_STATIC) + list(APPEND LSLTargets lslobj lslboost) +endif() +install(TARGETS ${LSLTargets} + EXPORT lslTargets # generates a CMake package config; should not be same name as the list of targets + COMPONENT liblsl + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + # If we use CMake 3.23 FILE_SET, replace INCLUDES line with: FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) +# Install the public headers. +# TODO: Verify that this is necessary, given that we already installed the INCLUDES above. +# TODO: Verify if it is still necessary to install the headers if we use FILE_SET. +install(DIRECTORY include/ + COMPONENT liblsl + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +# Generate and install CMake package config. +# This allows other CMake projects to find and use the lsl library +# using find_package(lsl). +include(CMakePackageConfigHelpers) + +# Generate a version file for the package. +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/LSLConfigVersion.cmake" + VERSION "${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH}" + COMPATIBILITY AnyNewerVersion +) + +# TODO: What does this do? Why do we need LSLTargets.cmake in the build dir? +export(EXPORT lslTargets + FILE "${CMAKE_CURRENT_BINARY_DIR}/LSLTargets.cmake" + NAMESPACE LSL:: +) + +# Generate the LSLConfig.cmake file and mark it for installation +install( + EXPORT lslTargets + FILE LSLTargets.cmake # TODO: I think we can use this to generate LSLConfig.cmake, no? + COMPONENT liblsl + NAMESPACE "LSL::" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL +) +# A common alternative to installing the exported package config file is to generate it from a template. +#configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/lslConfig.cmake.in +# ${CMAKE_CURRENT_BINARY_DIR}/LSLConfig.cmake +# INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/lsl) +# If we use this method, then we need a corresponding install(FILES ...) command to install the generated file. + +# Copy hardcoded CMake files to the build directory. +# TODO: Why bother with this copy? Is it not enough to install (into cmake/LSL)? +configure_file(cmake/LSLCMake.cmake "${CMAKE_CURRENT_BINARY_DIR}/LSLCMake.cmake" COPYONLY) +# TODO: Why bother with this copy? Is it not enough to install (into cmake/LSL)? +# TODO: Why use hardcoded files? We can generate the LSLConfig.cmake. +configure_file(cmake/LSLConfig.cmake "${CMAKE_CURRENT_BINARY_DIR}/LSLConfig.cmake" COPYONLY) + +# Install the version file and the helper CMake script. +install( + FILES + # TODO: Keep this. But why does the configure_file(... COPYONLY) above exist? + cmake/LSLCMake.cmake + # TODO: Next line shouldn't be necessary if install(EXPORT...) uses LSLConfig.cmake instead of LSLTargets.cmake + ${CMAKE_CURRENT_BINARY_DIR}/LSLConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/LSLConfigVersion.cmake + COMPONENT liblsl + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL +) diff --git a/cmake/ProjectOptions.cmake b/cmake/ProjectOptions.cmake new file mode 100644 index 00000000..f0f605d0 --- /dev/null +++ b/cmake/ProjectOptions.cmake @@ -0,0 +1,13 @@ +# Project build options +option(LSL_DEBUGLOG "Enable (lots of) additional debug messages" OFF) +option(LSL_UNIXFOLDERS "Use the unix folder layout for install targets" ON) +option(LSL_BUILD_STATIC "Build LSL as a 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_BUNDLED_BOOST "Use the bundled Boost by default" ON) +option(LSL_BUNDLED_PUGIXML "Use the bundled pugixml by default" ON) +option(LSL_TOOLS "Build some experimental tools for in-depth tests" OFF) +option(LSL_BUILD_EXAMPLES "Build example programs in examples/" OFF) +option(LSL_UNITTESTS "Build LSL library unit tests" OFF) +option(LSL_FORCE_FANCY_LIBNAME "Add library name decorations (32/64/-debug)" OFF) +mark_as_advanced(LSL_FORCE_FANCY_LIBNAME) diff --git a/cmake/SourceFiles.cmake b/cmake/SourceFiles.cmake new file mode 100644 index 00000000..603172bb --- /dev/null +++ b/cmake/SourceFiles.cmake @@ -0,0 +1,82 @@ +set(lslsources + src/api_config.cpp + src/api_config.h + src/api_types.hpp + src/cancellable_streambuf.h + src/cancellation.h + src/cancellation.cpp + src/common.cpp + src/common.h + src/consumer_queue.cpp + src/consumer_queue.h + src/data_receiver.cpp + src/data_receiver.h + src/forward.h + src/info_receiver.cpp + src/info_receiver.h + src/inlet_connection.cpp + src/inlet_connection.h + src/lsl_resolver_c.cpp + src/lsl_inlet_c.cpp + src/lsl_outlet_c.cpp + src/lsl_streaminfo_c.cpp + src/lsl_xml_element_c.cpp + src/netinterfaces.h + src/netinterfaces.cpp + src/portable_archive/portable_archive_exception.hpp + src/portable_archive/portable_archive_includes.hpp + src/portable_archive/portable_iarchive.hpp + src/portable_archive/portable_oarchive.hpp + src/resolver_impl.cpp + src/resolver_impl.h + src/resolve_attempt_udp.cpp + src/resolve_attempt_udp.h + src/sample.cpp + src/sample.h + src/send_buffer.cpp + src/send_buffer.h + src/socket_utils.cpp + src/socket_utils.h + src/stream_info_impl.cpp + src/stream_info_impl.h + src/stream_inlet_impl.h + src/stream_outlet_impl.cpp + src/stream_outlet_impl.h + src/tcp_server.cpp + src/tcp_server.h + src/time_postprocessor.cpp + src/time_postprocessor.h + src/time_receiver.cpp + src/time_receiver.h + src/udp_server.cpp + src/udp_server.h + src/util/cast.hpp + src/util/cast.cpp + src/util/endian.cpp + src/util/endian.hpp + src/util/inireader.hpp + src/util/inireader.cpp + src/util/strfuns.hpp + src/util/strfuns.cpp + src/util/uuid.hpp + thirdparty/loguru/loguru.cpp + $<$:src/legacy/legacy_abi.cpp src/legacy/legacy_abi.h> +) +set(lslheaders + include/lsl_c.h + include/lsl_cpp.h + include/lsl/common.h + include/lsl/inlet.h + include/lsl/outlet.h + include/lsl/resolver.h + include/lsl/streaminfo.h + include/lsl/types.h + include/lsl/xml.h +) +# LSL_LIB_TYPE set by ProjectOptions.cmake +# LSL_VERSION_INFO set by GitVersion.cmake < Dependencies.cmake +# These are used to set the version information in the buildinfo.cpp file +set_source_files_properties("src/buildinfo.cpp" + PROPERTIES COMPILE_DEFINITIONS + LSL_LIBRARY_INFO_STR="${LSL_VERSION_INFO}/link:${LSL_LIB_TYPE}" +) diff --git a/cmake/TargetLib.cmake b/cmake/TargetLib.cmake new file mode 100644 index 00000000..012c232c --- /dev/null +++ b/cmake/TargetLib.cmake @@ -0,0 +1,45 @@ +# Create main 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) + +# Configure main library + +# Set compile definitions for lsl +target_compile_definitions(lsl + PUBLIC + # defines for LSL_CPP_API export header (shared: dllimport/dllexport) + $,LIBLSL_STATIC,LIBLSL_EXPORTS> + # don't use #pragma(lib) in MSVC builds. TODO: Maybe this can be inherited from lslobj or removed on lslobj? + $<$:LSLNOAUTOLINK> + PRIVATE + $<$:DEBUGLOG> +) + +# Includes. TODO: Can we not inherit these from lslobj? +target_include_directories(lsl + INTERFACE + $ + $ +) + +# Link dependencies +target_link_libraries(lsl + PRIVATE + lslobj # TODO: If this is public, does that improve inheritance of includes and compile definitions? + lslboost # TODO: Shouldn't be needed -- lslobj already links it + ${PUGIXML_LIBRARIES} +) + +set_target_properties(lsl PROPERTIES + VERSION ${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH} + SOVERSION ${LSL_ABI_VERSION} +) +if(LSL_FORCE_FANCY_LIBNAME) + math(EXPR lslplatform "8 * ${CMAKE_SIZEOF_VOID_P}") + set_target_properties(lsl PROPERTIES + PREFIX "" + OUTPUT_NAME "liblsl${lslplatform}" + DEBUG_POSTFIX "-debug" + ) +endif() diff --git a/cmake/TargetObjLib.cmake b/cmake/TargetObjLib.cmake new file mode 100644 index 00000000..32772dfe --- /dev/null +++ b/cmake/TargetObjLib.cmake @@ -0,0 +1,89 @@ +# Create object library so all files are only compiled once +add_library(lslobj OBJECT + ${lslsources} + ${lslheaders} +) + +target_compile_features(lslobj PUBLIC cxx_std_17) # Note: Redundant with project-wide setting in CompilerSettings.cmake + +target_compile_definitions(lslobj + PRIVATE + LIBLSL_EXPORTS + LOGURU_DEBUG_LOGGING=$ + PUBLIC + ASIO_NO_DEPRECATED + $<$:LSLNOAUTOLINK> # don't use #pragma(lib) in CMake builds +) +if(WIN32) + # TODO: Maybe these can be moved above with boolean conditionals? + target_compile_definitions(lslobj + PRIVATE + _CRT_SECURE_NO_WARNINGS + PUBLIC + _WIN32_WINNT=${LSL_WINVER} + ) +endif(WIN32) + +# Set the includes/headers for the lslobj target. +# Note: We cannot use the PUBLIC_HEADER property of the target, because +# it flattens the include directories. +# We could use the new FILE_SET feature that comes with CMake 3.23. +# This is how it would look. Note that HEADERS is a special set name and implies its type. +#target_sources(lslobj +# PUBLIC +# FILE_SET HEADERS +# BASE_DIRS include +# FILES ${lslheaders} +#) +# We settle on the older and more common target_include_directories PUBLIC approach. +# If we used the FILET_SET approach then we would remove the PUBLIC includes below. +target_include_directories(lslobj + PUBLIC + $ + $ + INTERFACE + # Propagate include directories to consumers + $ # for unit tests +) + +# Link in dependencies -- some of which are header-only libraries +# - System libs +if(UNIX AND NOT APPLE) + # check that clock_gettime is present in the stdlib, link against librt otherwise + include(CheckSymbolExists) + check_symbol_exists(clock_gettime time.h HAS_GETTIME) + if(NOT HAS_GETTIME) + target_link_libraries(lslobj PRIVATE rt) + endif() + if(LSL_DEBUGLOG) + target_link_libraries(lslobj PRIVATE dl) + endif() +elseif(WIN32) + target_link_libraries(lslobj PRIVATE iphlpapi winmm mswsock ws2_32) +endif() +if(MINGW) + target_link_libraries(lslobj PRIVATE bcrypt) +endif() +target_link_libraries(lslobj PRIVATE lslboost Threads::Threads) +# - loguru and asio header-only +if(NOT LSL_OPTIMIZATIONS) + # 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(lslobj PRIVATE thirdparty/asio_objects.cpp) + target_compile_definitions(lslobj PUBLIC ASIO_SEPARATE_COMPILATION ASIO_DISABLE_VISIBILITY) +endif() +target_include_directories(lslobj + SYSTEM PUBLIC + $ + $ +) +# - pugixml +if(LSL_BUNDLED_PUGIXML) + target_sources(lslobj PRIVATE thirdparty/pugixml/pugixml.cpp) + target_include_directories(lslobj + SYSTEM PUBLIC + $ + ) +else() + target_link_libraries(lslobj PUBLIC pugixml::pugixml) +endif() diff --git a/cmake/TargetOther.cmake b/cmake/TargetOther.cmake new file mode 100644 index 00000000..32b66dab --- /dev/null +++ b/cmake/TargetOther.cmake @@ -0,0 +1,11 @@ +# Build utilities +add_executable(lslver testing/lslver.c) +target_link_libraries(lslver PRIVATE lsl) +installLSLApp(lslver) + +if(NOT WIN32 AND LSL_TOOLS) + add_executable(blackhole testing/blackhole.cpp) + target_link_libraries(blackhole PRIVATE Threads::Threads) + target_include_directories(blackhole PRIVATE "thirdparty/asio/") + installLSLApp(blackhole) +endif() From 052d83a2d62e7c6e64f90ce294bc1055441c92c3 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 13:45:37 -0400 Subject: [PATCH 2/9] Update runner for MinGW static CI and install cmake in msys2 shell. --- .github/workflows/mingw_static.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mingw_static.yml b/.github/workflows/mingw_static.yml index c9b70b2d..31157711 100644 --- a/.github/workflows/mingw_static.yml +++ b/.github/workflows/mingw_static.yml @@ -19,7 +19,7 @@ jobs: build: name: MinGW batteries-included runs-on: windows-latest - + defaults: run: shell: 'msys2 {0}' @@ -29,6 +29,9 @@ jobs: - uses: msys2/setup-msys2@v2 with: release: false + cache: true + install: >- + cmake - name: Configure CMake run: | cmake --version @@ -41,7 +44,7 @@ jobs: -Dlslgitrevision=${{ github.sha }} \ -Dlslgitbranch=${{ github.ref }} \ -DLSL_OPTIMIZATIONS=OFF \ - -G 'MSYS Makefiles' + -G Ninja - name: make run: cmake --build build --target install --config Release -j --verbose From 49a2c4e8404ae99cfdf5fcb863ae7a1556d53371 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 14:44:07 -0400 Subject: [PATCH 3/9] Revert a small change to cmake installation commands order and one of the variable names. --- cmake/Installation.cmake | 52 +++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/cmake/Installation.cmake b/cmake/Installation.cmake index 72703c28..71003cbc 100644 --- a/cmake/Installation.cmake +++ b/cmake/Installation.cmake @@ -1,4 +1,5 @@ # Configure installation +include(CMakePackageConfigHelpers) # Paths if(LSL_UNIXFOLDERS) @@ -9,13 +10,22 @@ else() set(CMAKE_INSTALL_INCLUDEDIR LSL/include) endif() +# Generate a version file for the package. +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/LSLConfigVersion.cmake" + VERSION "${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH}" + COMPATIBILITY AnyNewerVersion +) + # Define installation targets set(LSLTargets lsl) if(LSL_BUILD_STATIC) list(APPEND LSLTargets lslobj lslboost) endif() + +# Install the targets and store configuration information. install(TARGETS ${LSLTargets} - EXPORT lslTargets # generates a CMake package config; should not be same name as the list of targets + EXPORT LSLTargets # generates a CMake package config; TODO: Why the same name as the list of targets? COMPONENT liblsl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -23,39 +33,19 @@ install(TARGETS ${LSLTargets} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # If we use CMake 3.23 FILE_SET, replace INCLUDES line with: FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) -# Install the public headers. -# TODO: Verify that this is necessary, given that we already installed the INCLUDES above. -# TODO: Verify if it is still necessary to install the headers if we use FILE_SET. -install(DIRECTORY include/ - COMPONENT liblsl - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) - -# Generate and install CMake package config. -# This allows other CMake projects to find and use the lsl library -# using find_package(lsl). -include(CMakePackageConfigHelpers) - -# Generate a version file for the package. -write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/LSLConfigVersion.cmake" - VERSION "${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH}" - COMPATIBILITY AnyNewerVersion -) # TODO: What does this do? Why do we need LSLTargets.cmake in the build dir? -export(EXPORT lslTargets +export(EXPORT LSLTargets FILE "${CMAKE_CURRENT_BINARY_DIR}/LSLTargets.cmake" NAMESPACE LSL:: ) # Generate the LSLConfig.cmake file and mark it for installation -install( - EXPORT lslTargets - FILE LSLTargets.cmake # TODO: I think we can use this to generate LSLConfig.cmake, no? - COMPONENT liblsl - NAMESPACE "LSL::" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL +install(EXPORT LSLTargets + FILE LSLTargets.cmake # TODO: I think we can use this to generate LSLConfig.cmake, no? + COMPONENT liblsl + NAMESPACE "LSL::" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/LSL ) # A common alternative to installing the exported package config file is to generate it from a template. #configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/lslConfig.cmake.in @@ -70,6 +60,14 @@ configure_file(cmake/LSLCMake.cmake "${CMAKE_CURRENT_BINARY_DIR}/LSLCMake.cmake" # TODO: Why use hardcoded files? We can generate the LSLConfig.cmake. configure_file(cmake/LSLConfig.cmake "${CMAKE_CURRENT_BINARY_DIR}/LSLConfig.cmake" COPYONLY) +# Install the public headers. +# TODO: Verify that this is necessary, given that we already installed the INCLUDES above. +# TODO: Verify if it is still necessary to install the headers if we use FILE_SET. +install(DIRECTORY include/ + COMPONENT liblsl + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + # Install the version file and the helper CMake script. install( FILES From ef09fb4a292780d91e29357c2284ced223f724a4 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 14:48:06 -0400 Subject: [PATCH 4/9] mingw - Revert changes; back to windows-2019 which doesn't run; at least we don't get a big red X. --- .github/workflows/mingw_static.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/mingw_static.yml b/.github/workflows/mingw_static.yml index 31157711..07004ed0 100644 --- a/.github/workflows/mingw_static.yml +++ b/.github/workflows/mingw_static.yml @@ -1,14 +1,14 @@ name: MinGW Windows static test on: - push: - branches: ['*'] - paths: - - '**' - - '!docs/**' - - '!.github/**' - - '.github/workflows/mingw_static.yml' - pull_request: +# push: +# branches: ['*'] +# paths: +# - '**' +# - '!docs/**' +# - '!.github/**' +# - '.github/workflows/mingw_static.yml' +# pull_request: workflow_dispatch: concurrency: @@ -18,7 +18,7 @@ concurrency: jobs: build: name: MinGW batteries-included - runs-on: windows-latest + runs-on: windows-2019 defaults: run: @@ -30,8 +30,8 @@ jobs: with: release: false cache: true - install: >- - cmake +# install: >- +# cmake - name: Configure CMake run: | cmake --version @@ -44,7 +44,7 @@ jobs: -Dlslgitrevision=${{ github.sha }} \ -Dlslgitbranch=${{ github.ref }} \ -DLSL_OPTIMIZATIONS=OFF \ - -G Ninja + -G 'MSYS Makefiles' - name: make run: cmake --build build --target install --config Release -j --verbose From 49052da64171f78237be95c4c659e6b2286cfec4 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 15:13:08 -0400 Subject: [PATCH 5/9] Change WINDOWS_EXPORT_ALL_SYMBOLS location to try to fix Windows build error. --- cmake/CompilerSettings.cmake | 2 +- cmake/TargetObjLib.cmake | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake index c43872b0..977cb12d 100644 --- a/cmake/CompilerSettings.cmake +++ b/cmake/CompilerSettings.cmake @@ -27,7 +27,7 @@ endif() # Platform-specific settings if(WIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS) - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + set(LSL_WINVER "0x0601" CACHE STRING "Windows version (_WIN32_WINNT) to target (defaults to 0x0601 for Windows 7)") elseif(APPLE) diff --git a/cmake/TargetObjLib.cmake b/cmake/TargetObjLib.cmake index 32772dfe..25644b30 100644 --- a/cmake/TargetObjLib.cmake +++ b/cmake/TargetObjLib.cmake @@ -15,7 +15,12 @@ target_compile_definitions(lslobj $<$:LSLNOAUTOLINK> # don't use #pragma(lib) in CMake builds ) if(WIN32) - # TODO: Maybe these can be moved above with boolean conditionals? + if(BUILD_SHARED_LIBS) + set_target_properties(lslobj + PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS ON + ) + endif(BUILD_SHARED_LIBS) target_compile_definitions(lslobj PRIVATE _CRT_SECURE_NO_WARNINGS From 5b6bcc9dca66786ee13b42eeeae0bd432b1e6e5d Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 17:30:26 -0400 Subject: [PATCH 6/9] Fix examples for modern MSVC --- examples/SendDataInChunks.cpp | 2 +- examples/SendMultipleStreams.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/SendDataInChunks.cpp b/examples/SendDataInChunks.cpp index 5e83ce7d..7192ebb4 100644 --- a/examples/SendDataInChunks.cpp +++ b/examples/SendDataInChunks.cpp @@ -133,7 +133,7 @@ int main(int argc, char **argv) { // Your device might have its own timer. Or you can decide how often to poll // your device, as we do here. - auto t_start = std::chrono::high_resolution_clock::now(); + auto t_start = std::chrono::steady_clock::now(); auto next_chunk_time = t_start; for (unsigned c = 0;; c++) { // wait a bit diff --git a/examples/SendMultipleStreams.cpp b/examples/SendMultipleStreams.cpp index 6bcc0544..97f0415b 100644 --- a/examples/SendMultipleStreams.cpp +++ b/examples/SendMultipleStreams.cpp @@ -2,8 +2,9 @@ #include #include #include +#include -using Clock = std::chrono::high_resolution_clock; +using Clock = std::chrono::steady_clock; int main(int argc, char **argv) { try { From ec436eb57956fced8581b0a76e9fa6d3fc2da097 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 17:32:47 -0400 Subject: [PATCH 7/9] Keep original order of cmake invocations as much as possible --- cmake/CompilerSettings.cmake | 16 ++++---- cmake/SourceFiles.cmake | 9 +---- cmake/TargetLib.cmake | 21 +++++----- cmake/TargetObjLib.cmake | 77 ++++++++++++++++++++---------------- 4 files changed, 62 insertions(+), 61 deletions(-) diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake index 977cb12d..31868a85 100644 --- a/cmake/CompilerSettings.cmake +++ b/cmake/CompilerSettings.cmake @@ -5,11 +5,8 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # generate a compilation database (compile_commands.json) for clang tooling set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# Enable position independent code for shared libraries -if(NOT LSL_BUILD_STATIC OR UNIX) - # shared libraries require relocatable symbols so we enable them by default - set(CMAKE_POSITION_INDEPENDENT_CODE ON) -endif() +set(LSL_WINVER "0x0601" CACHE STRING + "Windows version (_WIN32_WINNT) to target (defaults to 0x0601 for Windows 7)") # Determine library type if(LSL_BUILD_STATIC) @@ -18,6 +15,12 @@ else() set(LSL_LIB_TYPE SHARED) endif() +# Enable position independent code for shared libraries +if(NOT LSL_BUILD_STATIC OR UNIX) + # shared libraries require relocatable symbols so we enable them by default + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + # Enable optimizations if requested if(LSL_OPTIMIZATIONS) # enable LTO (https://en.wikipedia.org/wiki/Interprocedural_optimization @@ -27,9 +30,6 @@ endif() # Platform-specific settings if(WIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS) - - set(LSL_WINVER "0x0601" CACHE STRING - "Windows version (_WIN32_WINNT) to target (defaults to 0x0601 for Windows 7)") elseif(APPLE) set(CMAKE_MACOSX_RPATH ON) endif() diff --git a/cmake/SourceFiles.cmake b/cmake/SourceFiles.cmake index 603172bb..e4f0c9a1 100644 --- a/cmake/SourceFiles.cmake +++ b/cmake/SourceFiles.cmake @@ -72,11 +72,4 @@ set(lslheaders include/lsl/streaminfo.h include/lsl/types.h include/lsl/xml.h -) -# LSL_LIB_TYPE set by ProjectOptions.cmake -# LSL_VERSION_INFO set by GitVersion.cmake < Dependencies.cmake -# These are used to set the version information in the buildinfo.cpp file -set_source_files_properties("src/buildinfo.cpp" - PROPERTIES COMPILE_DEFINITIONS - LSL_LIBRARY_INFO_STR="${LSL_VERSION_INFO}/link:${LSL_LIB_TYPE}" -) +) \ No newline at end of file diff --git a/cmake/TargetLib.cmake b/cmake/TargetLib.cmake index 012c232c..2e541307 100644 --- a/cmake/TargetLib.cmake +++ b/cmake/TargetLib.cmake @@ -1,6 +1,10 @@ # Create main 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. +set_source_files_properties("src/buildinfo.cpp" + PROPERTIES COMPILE_DEFINITIONS + LSL_LIBRARY_INFO_STR="${LSL_VERSION_INFO}/link:${LSL_LIB_TYPE}" +) add_library(lsl ${LSL_LIB_TYPE} src/buildinfo.cpp) # Configure main library @@ -12,8 +16,13 @@ target_compile_definitions(lsl $,LIBLSL_STATIC,LIBLSL_EXPORTS> # don't use #pragma(lib) in MSVC builds. TODO: Maybe this can be inherited from lslobj or removed on lslobj? $<$:LSLNOAUTOLINK> - PRIVATE - $<$:DEBUGLOG> +) + +target_link_libraries(lsl + PRIVATE + lslobj # TODO: If this is public, does that improve inheritance of includes and compile definitions? + lslboost # TODO: Shouldn't be needed -- lslobj already links it + ${PUGIXML_LIBRARIES} ) # Includes. TODO: Can we not inherit these from lslobj? @@ -23,14 +32,6 @@ target_include_directories(lsl $ ) -# Link dependencies -target_link_libraries(lsl - PRIVATE - lslobj # TODO: If this is public, does that improve inheritance of includes and compile definitions? - lslboost # TODO: Shouldn't be needed -- lslobj already links it - ${PUGIXML_LIBRARIES} -) - set_target_properties(lsl PROPERTIES VERSION ${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH} SOVERSION ${LSL_ABI_VERSION} diff --git a/cmake/TargetObjLib.cmake b/cmake/TargetObjLib.cmake index 25644b30..68cd8249 100644 --- a/cmake/TargetObjLib.cmake +++ b/cmake/TargetObjLib.cmake @@ -4,30 +4,9 @@ add_library(lslobj OBJECT ${lslheaders} ) -target_compile_features(lslobj PUBLIC cxx_std_17) # Note: Redundant with project-wide setting in CompilerSettings.cmake +target_link_libraries(lslobj PRIVATE lslboost Threads::Threads) # TODO: Seems out of order here -target_compile_definitions(lslobj - PRIVATE - LIBLSL_EXPORTS - LOGURU_DEBUG_LOGGING=$ - PUBLIC - ASIO_NO_DEPRECATED - $<$:LSLNOAUTOLINK> # don't use #pragma(lib) in CMake builds -) -if(WIN32) - if(BUILD_SHARED_LIBS) - set_target_properties(lslobj - PROPERTIES - WINDOWS_EXPORT_ALL_SYMBOLS ON - ) - endif(BUILD_SHARED_LIBS) - target_compile_definitions(lslobj - PRIVATE - _CRT_SECURE_NO_WARNINGS - PUBLIC - _WIN32_WINNT=${LSL_WINVER} - ) -endif(WIN32) +target_compile_features(lslobj PUBLIC cxx_std_17) # TODO: Redundant with project-wide setting in CompilerSettings.cmake # Set the includes/headers for the lslobj target. # Note: We cannot use the PUBLIC_HEADER property of the target, because @@ -44,14 +23,32 @@ endif(WIN32) # If we used the FILET_SET approach then we would remove the PUBLIC includes below. target_include_directories(lslobj PUBLIC - $ + $ $ INTERFACE # Propagate include directories to consumers $ # for unit tests ) -# Link in dependencies -- some of which are header-only libraries +target_include_directories(lslobj + SYSTEM PUBLIC + $ + $ +) + +target_compile_definitions(lslobj + PRIVATE + LIBLSL_EXPORTS + LOGURU_DEBUG_LOGGING=$ + PUBLIC + ASIO_NO_DEPRECATED + $<$:LSLNOAUTOLINK> # don't use #pragma(lib) in CMake builds +) + +if(MINGW) + target_link_libraries(lslobj PRIVATE bcrypt) +endif() + # - System libs if(UNIX AND NOT APPLE) # check that clock_gettime is present in the stdlib, link against librt otherwise @@ -65,23 +62,33 @@ if(UNIX AND NOT APPLE) endif() elseif(WIN32) target_link_libraries(lslobj PRIVATE iphlpapi winmm mswsock ws2_32) + target_compile_definitions(lslobj + PRIVATE + _CRT_SECURE_NO_WARNINGS + PUBLIC + _WIN32_WINNT=${LSL_WINVER} + ) + if(BUILD_SHARED_LIBS) + # set_target_properties(lslobj + # PROPERTIES + # WINDOWS_EXPORT_ALL_SYMBOLS ON + # ) + endif(BUILD_SHARED_LIBS) endif() -if(MINGW) - target_link_libraries(lslobj PRIVATE bcrypt) -endif() -target_link_libraries(lslobj PRIVATE lslboost Threads::Threads) + +# Link in dependencies -- some of which are header-only libraries + # - loguru and asio header-only if(NOT LSL_OPTIMIZATIONS) # 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(lslobj PRIVATE thirdparty/asio_objects.cpp) - target_compile_definitions(lslobj PUBLIC ASIO_SEPARATE_COMPILATION ASIO_DISABLE_VISIBILITY) + target_compile_definitions(lslobj + PUBLIC + ASIO_SEPARATE_COMPILATION + ASIO_DISABLE_VISIBILITY + ) endif() -target_include_directories(lslobj - SYSTEM PUBLIC - $ - $ -) # - pugixml if(LSL_BUNDLED_PUGIXML) target_sources(lslobj PRIVATE thirdparty/pugixml/pugixml.cpp) From 08c671fb1a5abc94ebd2ad65323391a60cecde52 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 21:20:15 -0400 Subject: [PATCH 8/9] Reorder lslobj cmake commands for slightly more logical grouping. --- cmake/TargetObjLib.cmake | 52 +++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/cmake/TargetObjLib.cmake b/cmake/TargetObjLib.cmake index 68cd8249..ad911f80 100644 --- a/cmake/TargetObjLib.cmake +++ b/cmake/TargetObjLib.cmake @@ -4,11 +4,7 @@ add_library(lslobj OBJECT ${lslheaders} ) -target_link_libraries(lslobj PRIVATE lslboost Threads::Threads) # TODO: Seems out of order here - -target_compile_features(lslobj PUBLIC cxx_std_17) # TODO: Redundant with project-wide setting in CompilerSettings.cmake - -# Set the includes/headers for the lslobj target. +# Set the includes/headers for the lslobj target # Note: We cannot use the PUBLIC_HEADER property of the target, because # it flattens the include directories. # We could use the new FILE_SET feature that comes with CMake 3.23. @@ -30,26 +26,11 @@ target_include_directories(lslobj $ # for unit tests ) -target_include_directories(lslobj - SYSTEM PUBLIC - $ - $ -) - -target_compile_definitions(lslobj - PRIVATE - LIBLSL_EXPORTS - LOGURU_DEBUG_LOGGING=$ - PUBLIC - ASIO_NO_DEPRECATED - $<$:LSLNOAUTOLINK> # don't use #pragma(lib) in CMake builds -) - +# Link system libs +target_link_libraries(lslobj PRIVATE lslboost Threads::Threads) if(MINGW) target_link_libraries(lslobj PRIVATE bcrypt) endif() - -# - System libs if(UNIX AND NOT APPLE) # check that clock_gettime is present in the stdlib, link against librt otherwise include(CheckSymbolExists) @@ -62,10 +43,22 @@ if(UNIX AND NOT APPLE) endif() elseif(WIN32) target_link_libraries(lslobj PRIVATE iphlpapi winmm mswsock ws2_32) +endif() + +# Compiler settings +target_compile_definitions(lslobj + PRIVATE + LIBLSL_EXPORTS + LOGURU_DEBUG_LOGGING=$ + PUBLIC + ASIO_NO_DEPRECATED + $<$:LSLNOAUTOLINK> # don't use #pragma(lib) in CMake builds +) +if(WIN32) target_compile_definitions(lslobj - PRIVATE + PRIVATE _CRT_SECURE_NO_WARNINGS - PUBLIC + PUBLIC _WIN32_WINNT=${LSL_WINVER} ) if(BUILD_SHARED_LIBS) @@ -74,11 +67,15 @@ elseif(WIN32) # WINDOWS_EXPORT_ALL_SYMBOLS ON # ) endif(BUILD_SHARED_LIBS) -endif() - -# Link in dependencies -- some of which are header-only libraries +endif(WIN32) +# Link in 3rd party dependencies # - loguru and asio header-only +target_include_directories(lslobj + SYSTEM PUBLIC + $ + $ +) if(NOT LSL_OPTIMIZATIONS) # 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 @@ -89,6 +86,7 @@ if(NOT LSL_OPTIMIZATIONS) ASIO_DISABLE_VISIBILITY ) endif() + # - pugixml if(LSL_BUNDLED_PUGIXML) target_sources(lslobj PRIVATE thirdparty/pugixml/pugixml.cpp) From a51c463a1b231dd67e9183c4049788f898f391d1 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Mon, 7 Jul 2025 21:31:01 -0400 Subject: [PATCH 9/9] Reorder lsl cmake commands for slightly more logical grouping. --- cmake/TargetLib.cmake | 48 ++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/cmake/TargetLib.cmake b/cmake/TargetLib.cmake index 2e541307..356c9c66 100644 --- a/cmake/TargetLib.cmake +++ b/cmake/TargetLib.cmake @@ -9,29 +9,7 @@ add_library(lsl ${LSL_LIB_TYPE} src/buildinfo.cpp) # Configure main library -# Set compile definitions for lsl -target_compile_definitions(lsl - PUBLIC - # defines for LSL_CPP_API export header (shared: dllimport/dllexport) - $,LIBLSL_STATIC,LIBLSL_EXPORTS> - # don't use #pragma(lib) in MSVC builds. TODO: Maybe this can be inherited from lslobj or removed on lslobj? - $<$:LSLNOAUTOLINK> -) - -target_link_libraries(lsl - PRIVATE - lslobj # TODO: If this is public, does that improve inheritance of includes and compile definitions? - lslboost # TODO: Shouldn't be needed -- lslobj already links it - ${PUGIXML_LIBRARIES} -) - -# Includes. TODO: Can we not inherit these from lslobj? -target_include_directories(lsl - INTERFACE - $ - $ -) - +# Some naming metadata for export set_target_properties(lsl PROPERTIES VERSION ${liblsl_VERSION_MAJOR}.${liblsl_VERSION_MINOR}.${liblsl_VERSION_PATCH} SOVERSION ${LSL_ABI_VERSION} @@ -44,3 +22,27 @@ if(LSL_FORCE_FANCY_LIBNAME) DEBUG_POSTFIX "-debug" ) endif() + +# Includes. TODO: Can we not inherit these from lslobj? +target_include_directories(lsl + INTERFACE + $ + $ +) + +# Link dependencies. The biggest dependency is lslobj, which contains the bulk of the library code. +target_link_libraries(lsl + PRIVATE + lslobj # TODO: If this is public, does that improve inheritance of includes and compile definitions? + lslboost # TODO: Shouldn't be needed -- lslobj already links it + ${PUGIXML_LIBRARIES} +) + +# Set compile definitions for lsl +target_compile_definitions(lsl + PUBLIC + # defines for LSL_CPP_API export header (shared: dllimport/dllexport) + $,LIBLSL_STATIC,LIBLSL_EXPORTS> + # don't use #pragma(lib) in MSVC builds. TODO: Maybe this can be inherited from lslobj or removed on lslobj? + $<$:LSLNOAUTOLINK> +)