diff --git a/CMakeLists.txt b/CMakeLists.txt index db21289f96..1ea3febac2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,8 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # cmake_minimum_required(VERSION 3.16) -project(CycloneDDS VERSION 0.11.0 LANGUAGES C) +# C++ is only for Iceoryx plugin +project(CycloneDDS VERSION 0.11.0 LANGUAGES C CXX) # Set a default build type if none was specified set(default_build_type "RelWithDebInfo") @@ -29,6 +30,28 @@ else() set(not_crosscompiling ON) endif() +# By default we do shared libraries (we really prefer shared libraries because of the +# plugins for IDLC, security, PSMX, ...) +# +# For static builds, we recommend doing a regular shared library build first, then +# building the static Cyclone library with CMAKE_CROSSCOMPILING set. This avoids the +# dynamic linking in IDLC of something involving the static library, and that in turn +# avoids a position-dependent/position-independent mess. +# +# Note that on Linux that mess can be partially resolved by defining +# +# CMAKE_POSITION_INDEPENDENT_CODE=1 +# +# resulting in a PIC static library, but that is in turn incompatible with the +# system-provided static libraries for OpenSSL. So much easier to avoid it for the rare +# case where it is needed. +# +# It appears that on macOS, all code is position independent and it'll work regardless. +option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +if(NOT BUILD_SHARED_LIBS AND NOT CMAKE_CROSSCOMPILING) + message(WARNING "It is probably best to build a static library as-if cross compiling (e.g., use -DCMAKE_CROSSCOMPILING=1 -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})") +endif() + # By default don't treat warnings as errors, else anyone building it with a different compiler that # just happens to generate a warning, as well as anyone adding or modifying something and making a # small mistake would run into errors. CI builds can be configured differently. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4209bc889d..ae00de44c6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -113,7 +113,7 @@ if(BUILD_IDLC) add_subdirectory(idl) endif() add_subdirectory(security) -add_subdirectory(core) if(ENABLE_ICEORYX) add_subdirectory(psmx_iox) endif() +add_subdirectory(core) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9b32e346fd..0db30e1fe8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -11,11 +11,7 @@ # include (GenerateExportHeader) -if (BUILD_SHARED_LIBS OR NOT DEFINED BUILD_SHARED_LIBS) - add_library(ddsc SHARED "") -else() - add_library(ddsc) -endif() +add_library(ddsc) if(BUILD_TESTING) set_property(TARGET ddsc PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS TRUE) @@ -66,6 +62,26 @@ include(cdr/CMakeLists.txt) include(ddsi/CMakeLists.txt) include(ddsc/CMakeLists.txt) +# The not-so-elegant inclusion of all configured plug-ins for static builds. At least it +# keeps most of the dirty things in one place. +if(NOT BUILD_SHARED_LIBS) + get_property(plugin_list GLOBAL PROPERTY cdds_plugin_list) + if(plugin_list) + list(JOIN plugin_list "," plugin_commasep) + target_compile_options(ddsc PRIVATE "-DPLUGINS=${plugin_commasep}") + target_link_libraries(ddsc PRIVATE ${plugin_list}) + foreach(plugin ${plugin_list}) + set(propname ${plugin}_symbols) + get_property(plugin_symbols GLOBAL PROPERTY ${propname}) + list(JOIN plugin_symbols "," plugin_symbols_commasep) + target_compile_options(ddsc PRIVATE "-DPLUGIN_SYMBOLS_${plugin}=${plugin_symbols_commasep}") + endforeach() + endif() + if(ENABLE_SSL) + target_link_libraries(ddsc PUBLIC security_openssl) + endif() +endif() + add_coverage(ddsc) target_link_libraries(ddsc PRIVATE "$") target_compile_definitions( diff --git a/src/core/cdr/CMakeLists.txt b/src/core/cdr/CMakeLists.txt index 31193cafb5..284a01b4c6 100644 --- a/src/core/cdr/CMakeLists.txt +++ b/src/core/cdr/CMakeLists.txt @@ -34,12 +34,7 @@ else() include(Generate) include(GenerateExportHeader) - if (BUILD_SHARED_LIBS OR NOT DEFINED BUILD_SHARED_LIBS) - add_library(cdr SHARED "") - else() - add_library(cdr) - endif() - + add_library(cdr) add_library(${PROJECT_NAME}::cdr ALIAS cdr) target_sources(cdr PRIVATE ${srcs_cdr} ${hdrs_private_cdr} ${CMAKE_CURRENT_LIST_DIR}/../../ddsrt/src/bswap.c) diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 1c0beb545c..dd21a6772d 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -133,7 +133,6 @@ install( DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT dev) -# TODO: improve test inclusion. -if((BUILD_TESTING) AND (BUILD_IDLC) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800"))) +if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800"))) add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/tests") endif() diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index c132829c1d..91b8af18d8 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -10,6 +10,7 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # include(CUnit) +include(Generate) idlc_generate(TARGET RoundTrip FILES RoundTrip.idl) idlc_generate(TARGET Space FILES Space.idl WARNINGS no-implicit-extensibility) @@ -100,9 +101,25 @@ set(ddsc_test_sources "test_oneliner.h" "cdrstream.c" "serdata_keys.c" - "psmx.c" ) +# PSMX tests are tricky in a static build: we have a PSMX plugin that is based on Cyclone +# so we can test the interface even when Iceoryx is not available, but supporting that +# plugin is too complicated in a static build: it introduces a circular dependency and +# that's too hard for me in CMake. +# +# On most platforms (Linux, Windows, macOS) we could still load it dynamically but that +# fails to work because the shared library then includes its own copy of Cyclone DDS and +# then the access to the application readers that the plugin needs is no longer possible +# because they live in the other copy of the library. +# +# Fortunately, running them with Iceoryx doesn't suffer from this. If we simply skip +# these tests in a static build without Iceoryx and then we ensure the static build on CI +# uses Iceoryx, we should be good. +if(BUILD_SHARED_LIBS OR (ENABLE_ICEORYX AND NOT DEFINED ENV{COLCON})) + list(APPEND ddsc_test_sources "psmx.c") +endif() + if(ENABLE_LIFESPAN) list(APPEND ddsc_test_sources "lifespan.c") endif() @@ -222,23 +239,24 @@ target_link_libraries(oneliner PRIVATE RoundTrip Space ddsc) # PSMX implementation with Cyclone as transport, for testing +if (BUILD_SHARED_LIBS) + idlc_generate(TARGET psmx_cdds_data FILES psmx_cdds_data.idl) + set(psmx_cdds_sources + "psmx_cdds_impl.c" + "psmx_cdds_impl.h") + add_library(psmx_cdds SHARED ${psmx_cdds_sources}) + target_include_directories( + psmx_cdds PRIVATE + "$" + "$") + target_link_libraries(psmx_cdds PRIVATE ddsc psmx_cdds_data) -idlc_generate(TARGET psmx_cdds_data FILES psmx_cdds_data.idl) -set(psmx_cdds_sources - "psmx_cdds_impl.c" - "psmx_cdds_impl.h") -add_library(psmx_cdds SHARED ${psmx_cdds_sources}) -target_include_directories( - psmx_cdds PRIVATE - "$" - "$") -target_link_libraries(psmx_cdds PRIVATE ddsc psmx_cdds_data) - -generate_export_header(psmx_cdds BASE_NAME PSMX_CDDS EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/psmx_cdds/export.h") + generate_export_header(psmx_cdds BASE_NAME PSMX_CDDS EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/psmx_cdds/export.h") -install(TARGETS psmx_cdds + install(TARGETS psmx_cdds LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endif() # If Iceoryx is available, then also run all PSMX tests using Iceoryx. Colcon complicates # things too much and it doesn't affect Cyclone's CI run anyway. @@ -285,14 +303,23 @@ kill -0 `cat ctest_fixture_iox_roudi.pid`") set_tests_properties(stop_roudi PROPERTIES FIXTURES_CLEANUP iox) set_tests_properties(start_roudi stop_roudi PROPERTIES RESOURCE_LOCK iox_lock) - # Construct Iceoryx-variants of all PSMX tests + # Construct Iceoryx-variants of all PSMX tests if building shared libraries, map them to + # Iceoryx in a static build (because I don't know how to delete tests!) get_property(test_names DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY TESTS) list(FILTER test_names INCLUDE REGEX "^CUnit_ddsc_psmx_[A-Za-z_0-9]+$") - foreach(fullname ${test_names}) - string(REGEX REPLACE "^CUnit_ddsc_psmx_(.*)" "\\1" shortname "${fullname}") - add_test(NAME ${fullname}_iox COMMAND cunit_ddsc -s ddsc_psmx -t ${shortname}) - set_tests_properties(${fullname}_iox PROPERTIES FIXTURES_REQUIRED iox) - set_tests_properties(${fullname}_iox PROPERTIES RESOURCE_LOCK iox_lock) - set_tests_properties(${fullname}_iox PROPERTIES ENVIRONMENT "CDDS_PSMX_NAME=iox;LD_LIBRARY_PATH=$:$ENV{LD_LIBRARY_PATH}") - endforeach() + if(BUILD_SHARED_LIBS) + foreach(fullname ${test_names}) + string(REGEX REPLACE "^CUnit_ddsc_psmx_(.*)" "\\1" shortname "${fullname}") + add_test(NAME ${fullname}_iox COMMAND cunit_ddsc -s ddsc_psmx -t ${shortname}) + set_tests_properties(${fullname}_iox PROPERTIES FIXTURES_REQUIRED iox) + set_tests_properties(${fullname}_iox PROPERTIES RESOURCE_LOCK iox_lock) + set_tests_properties(${fullname}_iox PROPERTIES ENVIRONMENT "CDDS_PSMX_NAME=iox;LD_LIBRARY_PATH=$:$ENV{LD_LIBRARY_PATH}") + endforeach() + else() + foreach(fullname ${test_names}) + set_tests_properties(${fullname} PROPERTIES FIXTURES_REQUIRED iox) + set_tests_properties(${fullname} PROPERTIES RESOURCE_LOCK iox_lock) + set_tests_properties(${fullname} PROPERTIES ENVIRONMENT "CDDS_PSMX_NAME=iox") + endforeach() + endif() endif() diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 0fe47b8ce1..b3d38e67e0 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -78,6 +78,7 @@ set(headers set(sources "${source_dir}/src/atomics.c" "${source_dir}/src/avl.c" + "${source_dir}/src/dynlib.c" "${source_dir}/src/bits.c" "${source_dir}/src/bswap.c" "${source_dir}/src/io.c" @@ -318,6 +319,10 @@ if(BUILD_TESTING) set(DDS_ALLOW_NESTED_DOMAIN 1) endif() +if (NOT BUILD_SHARED_LIBS) + set(DDS_IS_STATIC_LIBRARY 1) +endif() + configure_file(include/dds/config.h.in include/dds/config.h) configure_file(include/dds/features.h.in include/dds/features.h) configure_file(include/dds/version.h.in include/dds/version.h) diff --git a/src/ddsrt/include/dds/ddsrt/countargs.h b/src/ddsrt/include/dds/ddsrt/countargs.h index a1f6f32908..1dde7c7393 100644 --- a/src/ddsrt/include/dds/ddsrt/countargs.h +++ b/src/ddsrt/include/dds/ddsrt/countargs.h @@ -18,9 +18,9 @@ #define DDSRT_COUNT_ARGS_MSVC_WORKAROUND(x) x -/** @brief Returns the number of arguments provided (at most 10) */ -#define DDSRT_COUNT_ARGS(...) DDSRT_COUNT_ARGS1 (__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1,0) +/** @brief Returns the number of arguments provided (at most 20) */ +#define DDSRT_COUNT_ARGS(...) DDSRT_COUNT_ARGS1 (__VA_ARGS__, 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) #define DDSRT_COUNT_ARGS1(...) DDSRT_COUNT_ARGS_MSVC_WORKAROUND (DDSRT_COUNT_ARGS_ARGN (__VA_ARGS__)) -#define DDSRT_COUNT_ARGS_ARGN(a,b,c,d,e,f,g,h,i,j,n,...) n +#define DDSRT_COUNT_ARGS_ARGN(a,b,c,d,e,f,g,h,i,j, k,l,m,n,o,p,q,r,s,t, N,...) N #endif diff --git a/src/ddsrt/include/dds/ddsrt/dynlib.h b/src/ddsrt/include/dds/ddsrt/dynlib.h index 58c544a5b5..6d78cf6420 100644 --- a/src/ddsrt/include/dds/ddsrt/dynlib.h +++ b/src/ddsrt/include/dds/ddsrt/dynlib.h @@ -64,6 +64,12 @@ ddsrt_dlopen( bool translate, ddsrt_dynlib_t *handle) ddsrt_nonnull_all; +dds_return_t +ddsrt_platform_dlopen( + const char *name, + bool translate, + ddsrt_dynlib_t *handle) ddsrt_nonnull_all; + /** * @brief Close the library. * @@ -86,6 +92,10 @@ dds_return_t ddsrt_dlclose( ddsrt_dynlib_t handle); +dds_return_t +ddsrt_platform_dlclose( + ddsrt_dynlib_t handle); + /** * @brief Get the memory address of a symbol. * @@ -111,6 +121,12 @@ ddsrt_dlsym( const char *symbol, void **address); +dds_return_t +ddsrt_platform_dlsym( + ddsrt_dynlib_t handle, + const char *symbol, + void **address); + /** * @brief Get the most recent library related error. * @@ -138,6 +154,11 @@ ddsrt_dlerror( char *buf, size_t buflen); +dds_return_t +ddsrt_platform_dlerror( + char *buf, + size_t buflen); + #if defined (__cplusplus) } #endif diff --git a/src/ddsrt/include/dds/features.h.in b/src/ddsrt/include/dds/features.h.in index 0bcf6f0bb1..28ac452333 100644 --- a/src/ddsrt/include/dds/features.h.in +++ b/src/ddsrt/include/dds/features.h.in @@ -41,4 +41,7 @@ /* Not for general use, specificly for testing psmx Cyclone DDS plugin */ #cmakedefine DDS_ALLOW_NESTED_DOMAIN 1 +/* Not intended for general use, whether building a static library, specifically testing psmx and security */ +#cmakedefine DDS_IS_STATIC_LIBRARY 1 + #endif diff --git a/src/ddsrt/src/dynlib.c b/src/ddsrt/src/dynlib.c new file mode 100644 index 0000000000..a0be151558 --- /dev/null +++ b/src/ddsrt/src/dynlib.c @@ -0,0 +1,167 @@ +#include +#include +#include + +#include "dds/ddsrt/countargs.h" +#include "dds/ddsrt/dynlib.h" + +// HACK, we shouldn't include this file if there are none +#ifdef PLUGINS + +#define FOREACH_3_1(f, sep, x) f(x) +#define FOREACH_3_2(f, sep, x, ...) f(x) sep() FOREACH_3_1(f, sep, __VA_ARGS__) +#define FOREACH_3_3(f, sep, x, ...) f(x) sep() FOREACH_3_2(f, sep, __VA_ARGS__) +#define FOREACH_3_4(f, sep, x, ...) f(x) sep() FOREACH_3_3(f, sep, __VA_ARGS__) +#define FOREACH_3_5(f, sep, x, ...) f(x) sep() FOREACH_3_4(f, sep, __VA_ARGS__) +#define FOREACH_3_6(f, sep, x, ...) f(x) sep() FOREACH_3_5(f, sep, __VA_ARGS__) +#define FOREACH_3_7(f, sep, x, ...) f(x) sep() FOREACH_3_6(f, sep, __VA_ARGS__) +#define FOREACH_3_8(f, sep, x, ...) f(x) sep() FOREACH_3_7(f, sep, __VA_ARGS__) +#define FOREACH_3_9(f, sep, x, ...) f(x) sep() FOREACH_3_8(f, sep, __VA_ARGS__) +#define FOREACH_3_10(f, sep, x, ...) f(x) sep() FOREACH_3_9(f, sep, __VA_ARGS__) +#define FOREACH_3_11(f, sep, x, ...) f(x) sep() FOREACH_3_10(f, sep, __VA_ARGS__) +#define FOREACH_3_12(f, sep, x, ...) f(x) sep() FOREACH_3_11(f, sep, __VA_ARGS__) +#define FOREACH_3_13(f, sep, x, ...) f(x) sep() FOREACH_3_12(f, sep, __VA_ARGS__) +#define FOREACH_3_14(f, sep, x, ...) f(x) sep() FOREACH_3_13(f, sep, __VA_ARGS__) +#define FOREACH_3_15(f, sep, x, ...) f(x) sep() FOREACH_3_14(f, sep, __VA_ARGS__) +#define FOREACH_3_16(f, sep, x, ...) f(x) sep() FOREACH_3_15(f, sep, __VA_ARGS__) +#define FOREACH_3_17(f, sep, x, ...) f(x) sep() FOREACH_3_16(f, sep, __VA_ARGS__) +#define FOREACH_3_18(f, sep, x, ...) f(x) sep() FOREACH_3_17(f, sep, __VA_ARGS__) +#define FOREACH_3_19(f, sep, x, ...) f(x) sep() FOREACH_3_18(f, sep, __VA_ARGS__) +#define FOREACH_3_20(f, sep, x, ...) f(x) sep() FOREACH_3_19(f, sep, __VA_ARGS__) +#define FOREACH_2(n, f, sep, ...) FOREACH_3_##n(f, sep, __VA_ARGS__) +#define FOREACH_1(n, f, sep, ...) FOREACH_2(n, f, sep, __VA_ARGS__) +#define FOREACH(f, sep, ...) FOREACH_1(DDSRT_COUNT_ARGS(__VA_ARGS__), f, sep, __VA_ARGS__) +#define FOREACH_WRAP(f, sep, ...) FOREACH(f, sep, __VA_ARGS__) + +// 2nd set of FOREACH macros because we need two levels of FOREACH's but the +// C preprocessor doesn't allow recursive macro expansion +#define FOREACH_B_3_1(f, sep, x) f(x) +#define FOREACH_B_3_2(f, sep, x, ...) f(x) sep() FOREACH_B_3_1(f, sep, __VA_ARGS__) +#define FOREACH_B_3_3(f, sep, x, ...) f(x) sep() FOREACH_B_3_2(f, sep, __VA_ARGS__) +#define FOREACH_B_3_4(f, sep, x, ...) f(x) sep() FOREACH_B_3_3(f, sep, __VA_ARGS__) +#define FOREACH_B_3_5(f, sep, x, ...) f(x) sep() FOREACH_B_3_4(f, sep, __VA_ARGS__) +#define FOREACH_B_3_6(f, sep, x, ...) f(x) sep() FOREACH_B_3_5(f, sep, __VA_ARGS__) +#define FOREACH_B_3_7(f, sep, x, ...) f(x) sep() FOREACH_B_3_6(f, sep, __VA_ARGS__) +#define FOREACH_B_3_8(f, sep, x, ...) f(x) sep() FOREACH_B_3_7(f, sep, __VA_ARGS__) +#define FOREACH_B_3_9(f, sep, x, ...) f(x) sep() FOREACH_B_3_8(f, sep, __VA_ARGS__) +#define FOREACH_B_3_10(f, sep, x, ...) f(x) sep() FOREACH_B_3_9(f, sep, __VA_ARGS__) +#define FOREACH_B_3_11(f, sep, x, ...) f(x) sep() FOREACH_B_3_10(f, sep, __VA_ARGS__) +#define FOREACH_B_3_12(f, sep, x, ...) f(x) sep() FOREACH_B_3_11(f, sep, __VA_ARGS__) +#define FOREACH_B_3_13(f, sep, x, ...) f(x) sep() FOREACH_B_3_12(f, sep, __VA_ARGS__) +#define FOREACH_B_3_14(f, sep, x, ...) f(x) sep() FOREACH_B_3_13(f, sep, __VA_ARGS__) +#define FOREACH_B_3_15(f, sep, x, ...) f(x) sep() FOREACH_B_3_14(f, sep, __VA_ARGS__) +#define FOREACH_B_3_16(f, sep, x, ...) f(x) sep() FOREACH_B_3_15(f, sep, __VA_ARGS__) +#define FOREACH_B_3_17(f, sep, x, ...) f(x) sep() FOREACH_B_3_16(f, sep, __VA_ARGS__) +#define FOREACH_B_3_18(f, sep, x, ...) f(x) sep() FOREACH_B_3_17(f, sep, __VA_ARGS__) +#define FOREACH_B_3_19(f, sep, x, ...) f(x) sep() FOREACH_B_3_18(f, sep, __VA_ARGS__) +#define FOREACH_B_3_20(f, sep, x, ...) f(x) sep() FOREACH_B_3_19(f, sep, __VA_ARGS__) +#define FOREACH_B_2(n, f, sep, ...) FOREACH_B_3_##n(f, sep, __VA_ARGS__) +#define FOREACH_B_1(n, f, sep, ...) FOREACH_B_2(n, f, sep, __VA_ARGS__) +#define FOREACH_B(f, sep, ...) FOREACH_B_1(DDSRT_COUNT_ARGS(__VA_ARGS__), f, sep, __VA_ARGS__) +#define FOREACH_B_WRAP(f, sep, ...) FOREACH_B(f, sep, __VA_ARGS__) + +#define COMMA() , +#define SEMICOLON() ; + +#define DLSYM_EXTERN(f) extern void f (void) +#define MAKE_DLSYM_EXTERNS_2(...) FOREACH_B(DLSYM_EXTERN, SEMICOLON, __VA_ARGS__) +#define MAKE_DLSYM_EXTERNS_1(...) MAKE_DLSYM_EXTERNS_2(__VA_ARGS__) +#define MAKE_DLSYM_EXTERNS(p) MAKE_DLSYM_EXTERNS_1(PLUGIN_SYMBOLS_##p) +FOREACH_WRAP (MAKE_DLSYM_EXTERNS, SEMICOLON, PLUGINS); + +struct static_dlsym_table { + const char *name; + void (*f) (void); +}; + +#define DLSYM_TABLE_ENTRY(f) { #f, f } +#define MAKE_DLSYM_TABLE_2(libname, ...) \ + static const struct static_dlsym_table static_dlsym_table_##libname[] = { \ + FOREACH_B(DLSYM_TABLE_ENTRY, COMMA, __VA_ARGS__), \ + { NULL, NULL } \ + } + +#define MAKE_DLSYM_TABLE_1(libname, ...) MAKE_DLSYM_TABLE_2(libname, __VA_ARGS__) +#define MAKE_DLSYM_TABLE(p) MAKE_DLSYM_TABLE_1(p, PLUGIN_SYMBOLS_##p) + +FOREACH_WRAP (MAKE_DLSYM_TABLE, SEMICOLON, PLUGINS); + +struct static_dlopen_table { + const char *name; + const struct static_dlsym_table *syms; +}; + +#define DLOPEN_TABLE_ENTRY(p) { #p, static_dlsym_table_##p } + +static const struct static_dlopen_table static_dlopen_table[] = { + FOREACH_WRAP(DLOPEN_TABLE_ENTRY, COMMA, PLUGINS), + { NULL, NULL } +}; + +dds_return_t ddsrt_dlopen (const char *name, bool translate, ddsrt_dynlib_t *handle) +{ + for (size_t i = 0; static_dlopen_table[i].name; i++) { + if (strcmp (static_dlopen_table[i].name, name) == 0) { + *handle = (ddsrt_dynlib_t) static_dlopen_table[i].syms; + return DDS_RETCODE_OK; + } + } + return ddsrt_platform_dlopen (name, translate, handle); +} + +dds_return_t ddsrt_dlclose (ddsrt_dynlib_t handle) +{ + for (size_t i = 0; static_dlopen_table[i].name; i++) + if (handle == (ddsrt_dynlib_t) static_dlopen_table[i].syms) + return DDS_RETCODE_OK; + return ddsrt_platform_dlclose (handle); +} + +static dds_return_t fake_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **address) +{ + const struct static_dlsym_table *t = (const struct static_dlsym_table *) handle; + for (size_t i = 0; t[i].name; i++) { + if (strcmp (t[i].name, symbol) == 0) { + *address = (void *) t[i].f; + return DDS_RETCODE_OK; + } + } + return DDS_RETCODE_ERROR; +} + +dds_return_t ddsrt_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **address) +{ + for (size_t i = 0; static_dlopen_table[i].name; i++) + if (handle == (ddsrt_dynlib_t) static_dlopen_table[i].syms) + return fake_dlsym (handle, symbol, address); + return ddsrt_platform_dlsym (handle, symbol, address); +} + +dds_return_t ddsrt_dlerror (char *buf, size_t buflen) +{ + return ddsrt_platform_dlerror (buf, buflen); +} + +#else + +dds_return_t ddsrt_dlopen (const char *name, bool translate, ddsrt_dynlib_t *handle) +{ + return ddsrt_platform_dlopen (name, translate, handle); +} + +dds_return_t ddsrt_dlclose (ddsrt_dynlib_t handle) +{ + return ddsrt_platform_dlclose (handle); +} + +dds_return_t ddsrt_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **address) +{ + return ddsrt_platform_dlsym (handle, symbol, address); +} + +dds_return_t ddsrt_dlerror (char *buf, size_t buflen) +{ + return ddsrt_platform_dlerror (buf, buflen); +} + +#endif diff --git a/src/ddsrt/src/dynlib/posix/dynlib.c b/src/ddsrt/src/dynlib/posix/dynlib.c index 27534c15ed..ff4eb4f490 100644 --- a/src/ddsrt/src/dynlib/posix/dynlib.c +++ b/src/ddsrt/src/dynlib/posix/dynlib.c @@ -17,7 +17,7 @@ #include "dds/ddsrt/io.h" #include "dds/ddsrt/string.h" -dds_return_t ddsrt_dlopen (const char *name, bool translate, ddsrt_dynlib_t *handle) +dds_return_t ddsrt_platform_dlopen (const char *name, bool translate, ddsrt_dynlib_t *handle) { assert (handle); *handle = NULL; @@ -45,13 +45,13 @@ dds_return_t ddsrt_dlopen (const char *name, bool translate, ddsrt_dynlib_t *han return *handle != NULL ? DDS_RETCODE_OK : DDS_RETCODE_ERROR; } -dds_return_t ddsrt_dlclose (ddsrt_dynlib_t handle) +dds_return_t ddsrt_platform_dlclose (ddsrt_dynlib_t handle) { assert (handle); return (dlclose (handle) == 0) ? DDS_RETCODE_OK : DDS_RETCODE_ERROR; } -dds_return_t ddsrt_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **address) +dds_return_t ddsrt_platform_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **address) { assert (handle); assert (address); @@ -60,7 +60,7 @@ dds_return_t ddsrt_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **addr return (*address == NULL) ? DDS_RETCODE_ERROR : DDS_RETCODE_OK; } -dds_return_t ddsrt_dlerror (char *buf, size_t buflen) +dds_return_t ddsrt_platform_dlerror (char *buf, size_t buflen) { assert (buf); assert (buflen); diff --git a/src/ddsrt/src/dynlib/windows/dynlib.c b/src/ddsrt/src/dynlib/windows/dynlib.c index 73bca461d5..8ba9e7bcc8 100644 --- a/src/ddsrt/src/dynlib/windows/dynlib.c +++ b/src/ddsrt/src/dynlib/windows/dynlib.c @@ -20,7 +20,7 @@ static ddsrt_thread_local DWORD dynlib_last_err; -dds_return_t ddsrt_dlopen (const char *name, bool translate, ddsrt_dynlib_t *handle) +dds_return_t ddsrt_platform_dlopen (const char *name, bool translate, ddsrt_dynlib_t *handle) { assert (handle); *handle = NULL; @@ -50,7 +50,7 @@ dds_return_t ddsrt_dlopen (const char *name, bool translate, ddsrt_dynlib_t *han return DDS_RETCODE_OK; } -dds_return_t ddsrt_dlclose (ddsrt_dynlib_t handle) +dds_return_t ddsrt_platform_dlclose (ddsrt_dynlib_t handle) { assert (handle); if (FreeLibrary ((HMODULE) handle) == 0) @@ -62,7 +62,7 @@ dds_return_t ddsrt_dlclose (ddsrt_dynlib_t handle) return DDS_RETCODE_OK; } -dds_return_t ddsrt_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **address) +dds_return_t ddsrt_platform_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **address) { assert (handle); assert (address); @@ -76,7 +76,7 @@ dds_return_t ddsrt_dlsym (ddsrt_dynlib_t handle, const char *symbol, void **addr return DDS_RETCODE_OK; } -dds_return_t ddsrt_dlerror (char *buf, size_t buflen) +dds_return_t ddsrt_platform_dlerror (char *buf, size_t buflen) { assert (buf); assert (buflen); diff --git a/src/psmx_iox/CMakeLists.txt b/src/psmx_iox/CMakeLists.txt index 8bd608f1a1..7c79d1c9ef 100644 --- a/src/psmx_iox/CMakeLists.txt +++ b/src/psmx_iox/CMakeLists.txt @@ -9,19 +9,37 @@ # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # -cmake_minimum_required(VERSION 3.10) -project(CycloneDDS-PSMX-IOX VERSION 0.11.0 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) +include(GenerateExportHeader) message(STATUS "Building Iceoryx PSMX plugin") -add_library(psmx_iox SHARED "src/psmx_iox_impl.cpp") +if(BUILD_SHARED_LIBS) + add_library(psmx_iox SHARED "src/psmx_iox_impl.cpp" "include/psmx_iox_impl.hpp") +else() + add_library(psmx_iox OBJECT "src/psmx_iox_impl.cpp" "include/psmx_iox_impl.hpp") + set_property(GLOBAL APPEND PROPERTY cdds_plugin_list psmx_iox) + set_property(GLOBAL PROPERTY psmx_iox_symbols iox_create_psmx) +endif() set_target_properties(psmx_iox PROPERTIES VERSION ${PROJECT_VERSION}) +generate_export_header(psmx_iox BASE_NAME DDS_PSMX_IOX EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/psmx_iox_export.h") -target_include_directories(psmx_iox PRIVATE "$") -target_link_libraries(psmx_iox PRIVATE ddsc iceoryx_hoofs::iceoryx_hoofs iceoryx_posh::iceoryx_posh) +target_include_directories(psmx_iox PRIVATE + "$" + "$" + "$" + "$" + "$" + "$" + "$") + +target_link_libraries(psmx_iox PRIVATE iceoryx_hoofs::iceoryx_hoofs iceoryx_posh::iceoryx_posh) +if(BUILD_SHARED_LIBS) + target_link_libraries(psmx_iox PRIVATE ddsc) +endif() install(TARGETS psmx_iox + EXPORT "${PROJECT_NAME}" LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/src/psmx_iox/include/psmx_iox_impl.hpp b/src/psmx_iox/include/psmx_iox_impl.hpp index f163fec10b..e448d58326 100644 --- a/src/psmx_iox/include/psmx_iox_impl.hpp +++ b/src/psmx_iox/include/psmx_iox_impl.hpp @@ -17,8 +17,9 @@ extern "C" { #include "dds/dds.h" #include "dds/ddsc/dds_loaned_sample.h" #include "dds/ddsc/dds_psmx.h" +#include "psmx_iox_export.h" -DDS_EXPORT dds_return_t iox_create_psmx (struct dds_psmx **psmx, dds_psmx_instance_id_t instance_id, const char *config); +DDS_PSMX_IOX_EXPORT dds_return_t iox_create_psmx (struct dds_psmx **psmx, dds_psmx_instance_id_t instance_id, const char *config); #if defined (__cplusplus) } diff --git a/src/security/builtin_plugins/access_control/CMakeLists.txt b/src/security/builtin_plugins/access_control/CMakeLists.txt index 3acb7fbe3e..cb56447e51 100644 --- a/src/security/builtin_plugins/access_control/CMakeLists.txt +++ b/src/security/builtin_plugins/access_control/CMakeLists.txt @@ -23,7 +23,13 @@ set(private_headers src/access_control.h ../include/ac_tokens.h) -add_library(dds_security_ac SHARED ${sources} ${private_headers}) +if(BUILD_SHARED_LIBS) + add_library(dds_security_ac SHARED ${sources} ${private_headers}) +else() + add_library(dds_security_ac OBJECT ${sources} ${private_headers}) + set_property(GLOBAL APPEND PROPERTY cdds_plugin_list dds_security_ac) + set_property(GLOBAL PROPERTY dds_security_ac_symbols init_access_control finalize_access_control) +endif() generate_export_header( dds_security_ac @@ -32,7 +38,9 @@ generate_export_header( ) target_link_libraries(dds_security_ac PRIVATE security_openssl) -target_link_libraries(dds_security_ac PUBLIC ddsc) +if(BUILD_SHARED_LIBS) + target_link_libraries(dds_security_ac PUBLIC ddsc) +endif() target_link_libraries(dds_security_ac PUBLIC OpenSSL::SSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties(dds_security_ac PROPERTIES LINK_FLAGS "/ignore:4099") diff --git a/src/security/builtin_plugins/authentication/CMakeLists.txt b/src/security/builtin_plugins/authentication/CMakeLists.txt index d6e7378146..a652c1ace6 100644 --- a/src/security/builtin_plugins/authentication/CMakeLists.txt +++ b/src/security/builtin_plugins/authentication/CMakeLists.txt @@ -21,7 +21,13 @@ set(private_headers src/authentication.h src/auth_utils.h) -add_library(dds_security_auth SHARED ${sources} ${private_headers}) +if(BUILD_SHARED_LIBS) + add_library(dds_security_auth SHARED ${sources} ${private_headers}) +else() + add_library(dds_security_auth OBJECT ${sources} ${private_headers}) + set_property(GLOBAL APPEND PROPERTY cdds_plugin_list dds_security_auth) + set_property(GLOBAL PROPERTY dds_security_auth_symbols init_authentication finalize_authentication) +endif() generate_export_header( dds_security_auth @@ -30,7 +36,9 @@ generate_export_header( ) target_link_libraries(dds_security_auth PRIVATE security_openssl) -target_link_libraries(dds_security_auth PUBLIC ddsc) +if(BUILD_SHARED_LIBS) + target_link_libraries(dds_security_auth PUBLIC ddsc) +endif() target_link_libraries(dds_security_auth PUBLIC OpenSSL::SSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties(dds_security_auth PROPERTIES LINK_FLAGS "/ignore:4099") diff --git a/src/security/builtin_plugins/cryptographic/CMakeLists.txt b/src/security/builtin_plugins/cryptographic/CMakeLists.txt index 670ffdc17c..ab2067d743 100644 --- a/src/security/builtin_plugins/cryptographic/CMakeLists.txt +++ b/src/security/builtin_plugins/cryptographic/CMakeLists.txt @@ -29,7 +29,13 @@ set(private_headers src/cryptography.h ../include/crypto_tokens.h) -add_library(dds_security_crypto SHARED ${sources} ${private_headers}) +if(BUILD_SHARED_LIBS) + add_library(dds_security_crypto SHARED ${sources} ${private_headers}) +else() + add_library(dds_security_crypto OBJECT ${sources} ${private_headers}) + set_property(GLOBAL APPEND PROPERTY cdds_plugin_list dds_security_crypto) + set_property(GLOBAL PROPERTY dds_security_crypto_symbols init_crypto finalize_crypto) +endif() generate_export_header( dds_security_crypto @@ -38,7 +44,9 @@ generate_export_header( ) target_link_libraries(dds_security_crypto PRIVATE security_openssl) -target_link_libraries(dds_security_crypto PUBLIC ddsc) +if(BUILD_SHARED_LIBS) + target_link_libraries(dds_security_crypto PUBLIC ddsc) +endif() target_link_libraries(dds_security_crypto PUBLIC OpenSSL::SSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties(dds_security_crypto PROPERTIES LINK_FLAGS "/ignore:4099") diff --git a/src/security/core/CMakeLists.txt b/src/security/core/CMakeLists.txt index c4cbbc7f34..418fb3eb45 100644 --- a/src/security/core/CMakeLists.txt +++ b/src/security/core/CMakeLists.txt @@ -45,7 +45,7 @@ target_include_directories(security_core "$>" ) -if(BUILD_TESTING AND BUILD_IDLC) +if(BUILD_TESTING) add_subdirectory(tests) endif() diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index c195693827..f934a23a93 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -11,6 +11,7 @@ # include (GenerateExportHeader) include (CUnit) +include (Generate) idlc_generate(TARGET SecurityCoreTests FILES SecurityCoreTests.idl WARNINGS no-implicit-extensibility) @@ -18,7 +19,36 @@ function(add_wrapper libname linklibs) set(srcs_wrapper "${CMAKE_CURRENT_LIST_DIR}/common/${libname}_wrapper.c" "${CMAKE_CURRENT_LIST_DIR}/common/plugin_wrapper_msg_q.c") - add_library("dds_security_${libname}_wrapper" SHARED "") + add_library("dds_security_${libname}_wrapper") + if(NOT BUILD_SHARED_LIBS) + set_property(GLOBAL APPEND PROPERTY cdds_plugin_list dds_security_${libname}_wrapper) + set_property(GLOBAL PROPERTY dds_security_${libname}_wrapper_symbols + init_test_${libname}_wrapped finalize_test_${libname}_wrapped + init_test_${libname}_missing_func finalize_test_${libname}_missing_func + init_test_${libname}_all_ok finalize_test_${libname}_all_ok) + if(libname STREQUAL authentication) + set_property(GLOBAL APPEND PROPERTY dds_security_${libname}_wrapper_symbols + init_test_${libname}_init_error finalize_test_${libname}_init_error) + elseif(libname STREQUAL access_control) + set_property(GLOBAL APPEND PROPERTY dds_security_${libname}_wrapper_symbols + init_test_${libname}_local_participant_not_allowed + init_test_${libname}_local_topic_not_allowed + init_test_${libname}_local_writer_not_allowed + init_test_${libname}_local_reader_not_allowed + init_test_${libname}_local_permissions_not_allowed + init_test_${libname}_remote_participant_not_allowed + init_test_${libname}_remote_topic_not_allowed + init_test_${libname}_remote_writer_not_allowed + init_test_${libname}_remote_reader_not_allowed + init_test_${libname}_remote_reader_relay_only + init_test_${libname}_remote_permissions_not_allowed + finalize_test_${libname}_not_allowed) + elseif(libname STREQUAL cryptography) + set_property(GLOBAL APPEND PROPERTY dds_security_${libname}_wrapper_symbols + init_test_${libname}_store_tokens finalize_test_${libname}_store_tokens + init_test_${libname}_plain_data finalize_test_${libname}_plain_data) + endif() + endif() if(CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties("dds_security_${libname}_wrapper" PROPERTIES LINK_FLAGS "/ignore:4099") endif() @@ -48,8 +78,10 @@ function(add_wrapper libname linklibs) target_link_libraries("dds_security_${libname}_wrapper" PRIVATE CycloneDDS::ucunit) target_include_directories("dds_security_${libname}_wrapper" PRIVATE "${CUNIT_DIR}/include") + if(BUILD_SHARED_LIBS) + target_link_libraries("dds_security_${libname}_wrapper" PUBLIC ddsc ${linklibs}) + endif() - target_link_libraries("dds_security_${libname}_wrapper" PUBLIC ddsc ${linklibs}) target_sources("dds_security_${libname}_wrapper" PRIVATE ${srcs_wrapper}) target_include_directories("dds_security_${libname}_wrapper" PUBLIC @@ -57,6 +89,7 @@ function(add_wrapper libname linklibs) "$>" "$>" "$" + "$" "$" "$" "$") @@ -109,7 +142,7 @@ target_include_directories( "$" "$" "$" - ) + ) if(ENABLE_SSL AND OPENSSL_FOUND) target_include_directories( cunit_security_core PRIVATE @@ -128,3 +161,9 @@ if(ENABLE_SSL AND OPENSSL_FOUND) target_link_libraries(cunit_security_core PRIVATE security_openssl) endif() target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + +if(NOT BUILD_SHARED_LIBS) + install(TARGETS dds_security_authentication_wrapper EXPORT "${PROJECT_NAME}") + install(TARGETS dds_security_cryptography_wrapper EXPORT "${PROJECT_NAME}") + install(TARGETS dds_security_access_control_wrapper EXPORT "${PROJECT_NAME}") +endif() diff --git a/src/security/core/tests/common/config_env.h.in b/src/security/core/tests/common/config_env.h.in index 8fdcea6400..fba35a91ae 100644 --- a/src/security/core/tests/common/config_env.h.in +++ b/src/security/core/tests/common/config_env.h.in @@ -12,14 +12,21 @@ #ifndef CONFIG_ENV_H #define CONFIG_ENV_H +#include "dds/features.h" + #define FILE_PATH_SEP "/" #define COMMON_ETC_DIR "@common_etc_dir@" #define PLUGIN_WRAPPER_LIB_DIR "@plugin_wrapper_lib_dir@" #define PLUGIN_WRAPPER_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@" #define PLUGIN_WRAPPER_LIB_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@" +// Statically linked plugins don't do path names +#ifdef DDS_IS_STATIC_LIBRARY +#define WRAPPERLIB_PATH(name) name +#else #define WRAPPERLIB_PATH(name) \ PLUGIN_WRAPPER_LIB_DIR FILE_PATH_SEP PLUGIN_WRAPPER_LIB_PREFIX name PLUGIN_WRAPPER_LIB_SUFFIX +#endif #define COMMON_ETC_PATH(name) \ COMMON_ETC_DIR FILE_PATH_SEP name diff --git a/src/security/openssl/CMakeLists.txt b/src/security/openssl/CMakeLists.txt index d1190b7247..4969b903fb 100644 --- a/src/security/openssl/CMakeLists.txt +++ b/src/security/openssl/CMakeLists.txt @@ -10,13 +10,48 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # -add_library(security_openssl INTERFACE) - -target_sources(security_openssl INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/src/openssl_support.c" - "${CMAKE_CURRENT_SOURCE_DIR}/include/dds/security/openssl_support.h") +# Ubuntu 22.04 shared library builds with ASAN fail with: +# +# /usr/bin/ld: ../../openssl/CMakeFiles/security_openssl.dir/src/openssl_support.c.o: \ +# warning: relocation against `__asan_option_detect_stack_use_after_return' in \ +# read-only section `.text' +# /usr/bin/ld: ../../openssl/CMakeFiles/security_openssl.dir/src/openssl_support.c.o: \ +# relocation R_X86_64_PC32 against symbol `__asan_option_detect_stack_use_after_return' \ +# can not be used when making a shared object; recompile with -fPIC +# +# Nowhere does it use this for something other than a shared library, so it seems to me +# that CMake is using incorrect build flags. Unfortunately, grokking CMake is beyond my +# abilities, so an ugly workaround will have to do for now. -target_include_directories( - security_openssl INTERFACE +if(BUILD_SHARED_LIBS) + add_library(security_openssl INTERFACE) + target_sources(security_openssl INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/src/openssl_support.c" + "${CMAKE_CURRENT_SOURCE_DIR}/include/dds/security/openssl_support.h") + target_include_directories( + security_openssl INTERFACE + "$") +else() + add_library(security_openssl OBJECT) + target_sources(security_openssl PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/src/openssl_support.c" + "${CMAKE_CURRENT_SOURCE_DIR}/include/dds/security/openssl_support.h") + target_include_directories( + security_openssl PUBLIC "$" -) + "$" + "$" + "$" + "$" + "$" + "$" + "$" + "$") + target_link_libraries(security_openssl PUBLIC OpenSSL::SSL) + install( + TARGETS security_openssl + EXPORT "${PROJECT_NAME}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib) +endif() diff --git a/src/ucunit/CMakeLists.txt b/src/ucunit/CMakeLists.txt index 0d31f2191b..49566101ac 100644 --- a/src/ucunit/CMakeLists.txt +++ b/src/ucunit/CMakeLists.txt @@ -11,11 +11,7 @@ # include (GenerateExportHeader) -if (BUILD_SHARED_LIBS OR NOT DEFINED BUILD_SHARED_LIBS) - add_library(ucunit SHARED "") -else() - add_library(ucunit) -endif() +add_library(ucunit) add_library(${PROJECT_NAME}::ucunit ALIAS ucunit) set(srcs_ucunit @@ -43,3 +39,12 @@ target_sources(test_ucunit PRIVATE tests/test_ucunit.c) target_link_libraries(test_ucunit CycloneDDS::ucunit) add_test(NAME ucunit COMMAND $/test_ucunit) + +if (NOT BUILD_SHARED_LIBS) + install( + TARGETS ucunit + EXPORT "${PROJECT_NAME}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib) +endif()