From 7465083759ef8ee2e119b3ee5ab6fd76ad8dc902 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 3 Sep 2021 15:29:50 +0200 Subject: [PATCH 01/37] Fix dlopen_path test on normal VS/Xcode This restores the directories used before the MinGW support was added. For some reason, in the CI the VS and Xcode builds do store the output in directories not suffixed with Release or Debug, but this is not usually the case. As a consequence, on a typical build with those build systems, this test failed. Signed-off-by: Erik Boasson --- src/ddsrt/tests/CMakeLists.txt | 53 +++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/ddsrt/tests/CMakeLists.txt b/src/ddsrt/tests/CMakeLists.txt index 73be8a2b96..def364f428 100644 --- a/src/ddsrt/tests/CMakeLists.txt +++ b/src/ddsrt/tests/CMakeLists.txt @@ -36,9 +36,32 @@ endif() if(HAVE_DYNLIB) list(APPEND sources dynlib.c) + # Create a separate shared library for testing dynamic loading + add_library(cunit_ddsrt_dynlib SHARED dl.c) + target_include_directories( + cunit_ddsrt_dynlib PRIVATE "$") + + # Make sure we know where to find the library, even on multi-target generators + # which seem to usually append Debug/Release/... to the directory, but not, it + # seems, on Azure. + set_target_properties( + cunit_ddsrt_dynlib + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} ) + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" test_lib_dir) + + # Make the location of the test library available to the test program set(test_lib_base "cunit_ddsrt_dynlib") if(WIN32) - file(TO_NATIVE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" test_lib_dir) # MinGW prefixes .dll files with lib by default set(test_lib_name "${CMAKE_SHARED_LIBRARY_PREFIX}${test_lib_base}") set(test_lib_sep "\\\\") @@ -47,21 +70,37 @@ if(HAVE_DYNLIB) string(REPLACE "/" "\\" test_lib_dir "${test_lib_dir}") endif() else() - file(TO_NATIVE_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" test_lib_dir) set(test_lib_name "${test_lib_base}") set(test_lib_sep "/") endif() set(test_lib_file "${CMAKE_SHARED_LIBRARY_PREFIX}${test_lib_base}${CMAKE_SHARED_LIBRARY_SUFFIX}") string(REPLACE "\\" "\\\\" test_lib_dir "${test_lib_dir}") configure_file(dl.h.in include/dl.h @ONLY) - - # Create a separate shared library for testing dynamic loading - add_library(cunit_ddsrt_dynlib SHARED dl.c) - target_include_directories( - cunit_ddsrt_dynlib PRIVATE "$") endif() add_cunit_executable(cunit_ddsrt ${sources}) + +# Ensure the directory containing the test library for the dlopen tests is in +# PATH/LD_LIBRARY_PATH (macOS is fine by virtue of rpath) so that the tests that do not +# specify the full file name can work. +# +# (Needs to be done after `add_cunit_executable`) +if(HAVE_DYNLIB) + unset(test_lib_tests) + process_cunit_source_file("dynlib.c" test_lib_header test_lib_suites test_lib_tests) + foreach(libtest ${test_lib_tests}) + string(REPLACE ":" ";" libtest ${libtest}) + list(GET libtest 0 suite) + list(GET libtest 1 test) + set(libtestname "CUnit_${suite}_${test}") + if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*") + set_property(TEST ${libtestname} APPEND PROPERTY ENVIRONMENT "${test_lib_dir}") + else() + set_property(TEST ${libtestname} APPEND PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${test_lib_dir};$ENV{LD_LIBRARY_PATH}") + endif() + endforeach() +endif() + add_coverage(cunit_ddsrt) target_link_libraries( cunit_ddsrt PRIVATE ddsrt) From 7b192076d5102201c38a8dac92dd81470e8ad41f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 17 Sep 2021 13:00:09 +0200 Subject: [PATCH 02/37] Avoid some undocumented interfaces in bison This fixes incompatibilities with bison 3.8: * returning user-defined values from yyparse is not supported, this works aruond that by storing a more meaningful return value in the parser state object; * the token name table generated by %token-table is deprecated and has been for quite some time, and it seems that now the accompanying mapping to internal token numbers is gone as well, this uses a hack to work around that. A follow-up fix is needed to remove the use of the token name table entirely. The hack here is attractive only in that it provides a quick solution for the failing CI runs on macOS. Signed-off-by: Erik Boasson --- src/idl/include/idl/processor.h | 1 + src/idl/src/parser.y | 28 +++++++++++++++------------- src/idl/src/processor.c | 23 ++++++++++------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/idl/include/idl/processor.h b/src/idl/include/idl/processor.h index 83ab2c3a90..1c2a7dab95 100644 --- a/src/idl/include/idl/processor.h +++ b/src/idl/include/idl/processor.h @@ -116,6 +116,7 @@ struct idl_pstate { IDL_PARSE_UNKNOWN_ANNOTATION_APPL_PARAMS } state; void *yypstate; /**< state of Bison generated parser */ + idl_retcode_t result; /**< return value from idl_parse */ } parser; }; diff --git a/src/idl/src/parser.y b/src/idl/src/parser.y index 8a7ebc6579..4f3c704d07 100644 --- a/src/idl/src/parser.y +++ b/src/idl/src/parser.y @@ -41,15 +41,16 @@ static void yyerror(idl_location_t *, idl_pstate_t *, const char *); #define NO_MEMORY() \ do { \ yylen = 0; \ - goto yyexhaustedlab; \ + pstate->parser.result = IDL_RETCODE_NO_MEMORY; \ + YYABORT; \ } while(0) #define SEMANTIC_ERROR(state, loc, ...) \ do { \ idl_error(state, loc, __VA_ARGS__); \ yylen = 0; /* pop right-hand side tokens */ \ - yyresult = IDL_RETCODE_SEMANTIC_ERROR; \ - goto yyreturn; \ + state->parser.result = IDL_RETCODE_SEMANTIC_ERROR; \ + YYABORT; \ } while(0) #define YYLLOC_DEFAULT(Cur, Rhs, N) \ @@ -75,19 +76,12 @@ static void yyerror(idl_location_t *, idl_pstate_t *, const char *); switch ((_ret_ = (action))) { \ case IDL_RETCODE_OK: \ break; \ - case IDL_RETCODE_NO_MEMORY: \ - yylen = 0; /* pop right-hand side tokens */ \ - (void)(except);\ - goto yyexhaustedlab; \ - case IDL_RETCODE_SYNTAX_ERROR: \ - yylen = 0; /* pop right-hand side tokens */ \ - (void)(except); \ - goto yyabortlab; \ default: \ yylen = 0; \ - yyresult = _ret_; \ (void)(except); \ - goto yyreturn; \ + pstate->parser.result = (_ret_); \ + YYABORT; \ + break; \ } \ } while(0) @@ -1102,7 +1096,14 @@ int idl_iskeyword(idl_pstate_t *pstate, const char *str, int nc) && cmp(yytname[i] + 1, str, n) == 0 && yytname[i][n + 1] == '"' && yytname[i][n + 2] == '\0') { +#if YYBISON >= 30800 + // "yytname" is long deprecated and "yytokname" has been removed in bison 3.8. + // This hack seems to be enough to buy us some time to rewrite the keyword + // recognition to not rely on anything deprecated + toknum = (int) (255 + i); +#else toknum = yytoknum[i]; +#endif } } @@ -1134,4 +1135,5 @@ static void yyerror(idl_location_t *loc, idl_pstate_t *pstate, const char *str) { idl_error(pstate, loc, str); + pstate->parser.result = IDL_RETCODE_SYNTAX_ERROR; } diff --git a/src/idl/src/processor.c b/src/idl/src/processor.c index bf84a8d14a..8c4d7a2c63 100644 --- a/src/idl/src/processor.c +++ b/src/idl/src/processor.c @@ -169,6 +169,7 @@ idl_create_pstate( pstate->keylists = false; pstate->annotations = false; pstate->parser.state = IDL_PARSE; + pstate->parser.result = IDL_RETCODE_BAD_PARAMETER; pstate->scanner.state = IDL_SCAN; memset(&pstate->buffer, 0, sizeof(pstate->buffer)); memset(&pstate->scanner, 0, sizeof(pstate->scanner)); @@ -294,7 +295,6 @@ idl_warning( static idl_retcode_t parse_grammar(idl_pstate_t *pstate, idl_token_t *tok) { - idl_retcode_t ret; IDL_YYSTYPE yylval; switch (tok->code) { @@ -316,23 +316,20 @@ static idl_retcode_t parse_grammar(idl_pstate_t *pstate, idl_token_t *tok) break; } - switch ((ret = idl_yypush_parse( - pstate->parser.yypstate, tok->code, &yylval, &tok->location, pstate))) + switch (idl_yypush_parse(pstate->parser.yypstate, tok->code, &yylval, &tok->location, pstate)) { - case 0: /* success */ - break; - case 1: /* parse error */ - return IDL_RETCODE_SYNTAX_ERROR; - case 2: /* out of memory */ + case 0: + return IDL_RETCODE_OK; + case 1: + return pstate->parser.result; + case 2: return IDL_RETCODE_NO_MEMORY; - case 4: /* push more */ + case YYPUSH_MORE: return IDL_RETCODE_PUSH_MORE; default: - assert(ret < 0); - return ret; + assert (0); } - - return IDL_RETCODE_OK; + return IDL_RETCODE_BAD_PARAMETER; } idl_retcode_t idl_parse(idl_pstate_t *pstate) From 320f5d04561cbc4ef7bd76b3c89f25620f5c9a2d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 21 Sep 2021 19:23:27 +0200 Subject: [PATCH 03/37] Move parser result into a separate argument Signed-off-by: Erik Boasson --- src/idl/include/idl/processor.h | 1 - src/idl/src/parser.y | 31 ++++++++++++++++--------------- src/idl/src/processor.c | 6 +++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/idl/include/idl/processor.h b/src/idl/include/idl/processor.h index 1c2a7dab95..83ab2c3a90 100644 --- a/src/idl/include/idl/processor.h +++ b/src/idl/include/idl/processor.h @@ -116,7 +116,6 @@ struct idl_pstate { IDL_PARSE_UNKNOWN_ANNOTATION_APPL_PARAMS } state; void *yypstate; /**< state of Bison generated parser */ - idl_retcode_t result; /**< return value from idl_parse */ } parser; }; diff --git a/src/idl/src/parser.y b/src/idl/src/parser.y index 4f3c704d07..6bc96ca527 100644 --- a/src/idl/src/parser.y +++ b/src/idl/src/parser.y @@ -35,21 +35,21 @@ _Pragma("GCC diagnostic ignored \"-Wanalyzer-free-of-non-heap\"") #endif #endif -static void yyerror(idl_location_t *, idl_pstate_t *, const char *); +static void yyerror(idl_location_t *, idl_pstate_t *, idl_retcode_t *, const char *); /* convenience macros to complement YYABORT */ #define NO_MEMORY() \ do { \ yylen = 0; \ - pstate->parser.result = IDL_RETCODE_NO_MEMORY; \ + *result = IDL_RETCODE_NO_MEMORY; \ YYABORT; \ } while(0) -#define SEMANTIC_ERROR(state, loc, ...) \ +#define SEMANTIC_ERROR(loc, ...) \ do { \ - idl_error(state, loc, __VA_ARGS__); \ + idl_error(pstate, loc, __VA_ARGS__); \ yylen = 0; /* pop right-hand side tokens */ \ - state->parser.result = IDL_RETCODE_SEMANTIC_ERROR; \ + *result = IDL_RETCODE_SEMANTIC_ERROR; \ YYABORT; \ } while(0) @@ -79,7 +79,7 @@ static void yyerror(idl_location_t *, idl_pstate_t *, const char *); default: \ yylen = 0; \ (void)(except); \ - pstate->parser.result = (_ret_); \ + *result = (_ret_); \ YYABORT; \ break; \ } \ @@ -157,6 +157,7 @@ void idl_yypstate_delete_stack(idl_yypstate *yyps); %locations %param { idl_pstate_t *pstate } +%parse-param { idl_retcode_t *result } %token-table @@ -360,7 +361,7 @@ const_type: TRY(idl_resolve(pstate, 0u, $1, &declaration)); node = idl_unalias(declaration->node, 0u); if (!(idl_mask(node) & (IDL_BASE_TYPE|IDL_STRING|IDL_ENUM))) - SEMANTIC_ERROR(pstate, &@1, fmt, $1->identifier); + SEMANTIC_ERROR(&@1, fmt, $1->identifier); $$ = idl_reference_node((idl_node_t *)declaration->node); idl_delete_scoped_name($1); } @@ -464,7 +465,7 @@ primary_expr: "Scoped name '%s' does not resolve to an enumerator or a contant"; TRY(idl_resolve(pstate, 0u, $1, &declaration)); if (!(idl_mask(declaration->node) & (IDL_CONST|IDL_ENUMERATOR))) - SEMANTIC_ERROR(pstate, &@1, fmt, $1->identifier); + SEMANTIC_ERROR(&@1, fmt, $1->identifier); $$ = idl_reference_node((idl_node_t *)declaration->node); } idl_delete_scoped_name($1); @@ -599,7 +600,7 @@ simple_type_spec: "Scoped name '%s' does not resolve to a type"; TRY(idl_resolve(pstate, 0u, $1, &declaration)); if (!declaration || !idl_is_type_spec(declaration->node)) - SEMANTIC_ERROR(pstate, &@1, fmt, $1->identifier); + SEMANTIC_ERROR(&@1, fmt, $1->identifier); $$ = idl_reference_node((idl_node_t *)declaration->node); idl_delete_scoped_name($1); } @@ -712,7 +713,7 @@ struct_inherit_spec: TRY(idl_resolve(pstate, 0u, $2, &declaration)); node = idl_unalias(declaration->node, 0u); if (!idl_is_struct(node)) - SEMANTIC_ERROR(pstate, &@2, fmt, $2->identifier); + SEMANTIC_ERROR(&@2, fmt, $2->identifier); TRY(idl_create_inherit_spec(pstate, &@2, idl_reference_node(node), &$$)); idl_delete_scoped_name($2); } @@ -889,7 +890,7 @@ identifier: else if (pstate->parser.state == IDL_PARSE_ANNOTATION) n = 0; else if (!(n = ($1[0] == '_')) && idl_iskeyword(pstate, $1, nocase)) - SEMANTIC_ERROR(pstate, &@1, "Identifier '%s' collides with a keyword", $1); + SEMANTIC_ERROR(&@1, "Identifier '%s' collides with a keyword", $1); if (pstate->parser.state != IDL_PARSE_UNKNOWN_ANNOTATION_APPL_PARAMS) TRY(idl_create_name(pstate, &@1, idl_strdup($1+n), &$$)); @@ -1034,7 +1035,7 @@ annotation_appl_keyword_param: if (declaration && (idl_mask(declaration->node) & IDL_DECLARATOR)) node = (idl_annotation_member_t *)((const idl_node_t *)declaration->node)->parent; if (!node || !(idl_mask(node) & IDL_ANNOTATION_MEMBER)) - SEMANTIC_ERROR(pstate, &@1, fmt, $1->identifier); + SEMANTIC_ERROR(&@1, fmt, $1->identifier); node = idl_reference_node((idl_node_t *)node); } $$ = node; @@ -1075,7 +1076,7 @@ void idl_yypstate_delete_stack(idl_yypstate *yyps) while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp, NULL); + yystos[*yyssp], yyvsp, yylsp, NULL, NULL); YYPOPSTACK (1); } } @@ -1132,8 +1133,8 @@ int idl_iskeyword(idl_pstate_t *pstate, const char *str, int nc) } static void -yyerror(idl_location_t *loc, idl_pstate_t *pstate, const char *str) +yyerror(idl_location_t *loc, idl_pstate_t *pstate, idl_retcode_t *result, const char *str) { idl_error(pstate, loc, str); - pstate->parser.result = IDL_RETCODE_SYNTAX_ERROR; + *result = IDL_RETCODE_SYNTAX_ERROR; } diff --git a/src/idl/src/processor.c b/src/idl/src/processor.c index 8c4d7a2c63..a0a9191c9a 100644 --- a/src/idl/src/processor.c +++ b/src/idl/src/processor.c @@ -169,7 +169,6 @@ idl_create_pstate( pstate->keylists = false; pstate->annotations = false; pstate->parser.state = IDL_PARSE; - pstate->parser.result = IDL_RETCODE_BAD_PARAMETER; pstate->scanner.state = IDL_SCAN; memset(&pstate->buffer, 0, sizeof(pstate->buffer)); memset(&pstate->scanner, 0, sizeof(pstate->scanner)); @@ -316,12 +315,13 @@ static idl_retcode_t parse_grammar(idl_pstate_t *pstate, idl_token_t *tok) break; } - switch (idl_yypush_parse(pstate->parser.yypstate, tok->code, &yylval, &tok->location, pstate)) + idl_retcode_t result = IDL_RETCODE_BAD_PARAMETER; + switch (idl_yypush_parse(pstate->parser.yypstate, tok->code, &yylval, &tok->location, pstate, &result)) { case 0: return IDL_RETCODE_OK; case 1: - return pstate->parser.result; + return result; case 2: return IDL_RETCODE_NO_MEMORY; case YYPUSH_MORE: From 7b64eccc879ee8b644cd6caff8dfd71ee6e3d6a7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 Sep 2021 14:31:38 +0200 Subject: [PATCH 04/37] Remove Visual Studio analyzer from builds The analyzer doesn't do a good job if there are no SAL2 annotations, but those annotations are only supported by Visual Studio, the documentation is very incomplete and it is (nearly) impossible to get them right without actually compiling the code with Visual Studio. The latter is what it makes it really impossible to use them. That makes dealing with false positives from the Visual Studio analzyer far more trouble than it is worth (especially considering we're also using the clang and gcc analyzers and Coverity). Signed-off-by: Erik Boasson --- CMakeLists.txt | 3 --- azure-pipelines.yml | 1 - 2 files changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e8eef19a7..76c0dc9334 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,9 +207,6 @@ if(ANALYZER) # -Wanalyzer-malloc-leak generates lots of false positives add_compile_options(-fanalyzer -Wno-analyzer-malloc-leak) endif() - elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") - message(STATUS "Enabling analyzer: MSVC") - add_compile_options(/analyze:stacksize 524288) endif() endif() endif() diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4425d56bd5..0b860b0730 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -81,7 +81,6 @@ strategy: toolset: v141 'Windows 2019 with Visual Studio 2019 (Debug, x86_64)': image: windows-2019 - analyzer: on generator: 'Visual Studio 16 2019' 'Windows 2019 with Visual Studio 2019 (Release, x86_64)': image: windows-2019 From 999d6a99481f785a09e9aeb9b89d9678ffde1ba0 Mon Sep 17 00:00:00 2001 From: liwei <12li-wei@163.com> Date: Fri, 3 Sep 2021 14:16:19 +0800 Subject: [PATCH 05/37] ddsrt_malloc size for maxq_list is incorrect in find_own_ip --- src/core/ddsi/src/ddsi_ownip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_ownip.c b/src/core/ddsi/src/ddsi_ownip.c index e5d09857af..5bb18d7f24 100644 --- a/src/core/ddsi/src/ddsi_ownip.c +++ b/src/core/ddsi/src/ddsi_ownip.c @@ -183,7 +183,7 @@ int find_own_ip (struct ddsi_domaingv *gv, const char *requested_address) n_interfaces = 0; max_interfaces = 8; - maxq_list = ddsrt_malloc (max_interfaces * sizeof (*interfaces)); + maxq_list = ddsrt_malloc (max_interfaces * sizeof (*maxq_list)); interfaces = ddsrt_malloc (max_interfaces * sizeof (*interfaces)); last_if_name[0] = 0; for (ifa = ifa_root; ifa != NULL; ifa = ifa->next) From a93b0b614dd9a4a210918be321c593e48bd3332d Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 7 Sep 2021 20:24:43 +0200 Subject: [PATCH 06/37] Use correct offset when serializing type consistency qos Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_plist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/ddsi_plist.c b/src/core/ddsi/src/ddsi_plist.c index 8a7aa2f0b5..e3d9879b2f 100644 --- a/src/core/ddsi/src/ddsi_plist.c +++ b/src/core/ddsi/src/ddsi_plist.c @@ -542,7 +542,7 @@ static dds_return_t ser_type_consistency (struct nn_xmsg *xmsg, nn_parameterid_t char * const p = nn_xmsg_addpar_bo (xmsg, pid, 8, bo); const uint16_t kind = ddsrt_toBO2u (bo, (uint16_t) x->kind); memcpy (p, &kind, 2); - size_t offs = sizeof (x->kind); + size_t offs = sizeof (kind); p[offs + 0] = x->force_type_validation; p[offs + 1] = x->ignore_sequence_bounds; p[offs + 2] = x->ignore_string_bounds; @@ -2498,7 +2498,7 @@ static enum do_locator_result do_locator (nn_locators_t *ls, uint64_t present, u loc.kind = ddsrt_bswap4 (loc.kind); loc.port = ddsrt_bswap4u (loc.port); } - + ddsi_tran_factory_t fact = ddsi_factory_find_supported_kind (gv, loc.kind); if (fact == NULL || !fact->m_enable) return DOLOC_IGNORED; From ba32af3f94ab3a8d4c29cbf9990127c93625255d Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 3 Sep 2021 10:23:17 +0200 Subject: [PATCH 07/37] Fix refcount bug on faulty annotations Signed-off-by: Jeroen Koekkoek --- src/idl/src/annotation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/idl/src/annotation.c b/src/idl/src/annotation.c index 5e10c38faf..7dfc4def67 100644 --- a/src/idl/src/annotation.c +++ b/src/idl/src/annotation.c @@ -650,7 +650,6 @@ idl_annotate( if ((ret = dedup(pstate, node, annotation_appls))) return ret; - ((idl_node_t *)node)->annotations = annotation_appls; for (idl_annotation_appl_t *a = annotation_appls; a; a = idl_next(a)) { idl_annotation_callback_t callback = a->annotation->callback; if (callback && (ret = callback(pstate, a, node))) @@ -658,5 +657,6 @@ idl_annotate( a->node.parent = node; } + ((idl_node_t *)node)->annotations = annotation_appls; return IDL_RETCODE_OK; } From 7707d26a597205f482db3761eec6481dfb542cb8 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 3 Sep 2021 14:16:44 +0200 Subject: [PATCH 08/37] Fix warning about possible use of uninitialized data Signed-off-by: Jeroen Koekkoek --- src/core/ddsc/tests/topic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index 8a1dc91a3b..466301b294 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -242,7 +242,7 @@ CU_Test(ddsc_topic_get_type_name, deleted, .init = ddsc_topic_init, .fini = ddsc CU_Test(ddsc_topic_set_qos, valid, .init = ddsc_topic_init, .fini = ddsc_topic_fini) { dds_return_t ret; - char data[10]; + char data[10] = { 0 }; dds_qset_topicdata(g_qos, &data, 10); ret = dds_set_qos(g_topic_rtmdt, g_qos); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); From fd646f027a29be13e3b20004ac7413049cf2b038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Bollo?= Date: Fri, 3 Sep 2021 18:27:19 +0200 Subject: [PATCH 09/37] Fix check of snprintf result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The length returned by snprintf does not includes the ending null. So the test must be changed to ensure that if the final length if sadly 64, the library can be found all the time. Also add little comments. Signed-off-by: José Bollo --- src/tools/idlc/src/plugin.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/idlc/src/plugin.c b/src/tools/idlc/src/plugin.c index 184bb09e40..52c4a4ecfc 100644 --- a/src/tools/idlc/src/plugin.c +++ b/src/tools/idlc/src/plugin.c @@ -86,15 +86,15 @@ idlc_load_generator(idlc_generator_plugin_t *plugin, const char *lang) /* figure out if user passed library or language */ if ((sep[0] && strchr(lang, sep[0])) || (sep[1] && strchr(lang, sep[1]))) { - path = lang; + path = lang; /* lang includes a directory separator, it is a path */ } else if (len > extlen && strcmp(lang + (len - extlen), ext) == 0) { - path = lang; + path = lang; /* lang terminates with extension of plugins (libs), it is a path */ } else { int cnt; - const char fmt[] = "%sidl%s.%s"; + const char fmt[] = "%sidl%s.%s"; /* builds the library name based on 'lang' */ cnt = snprintf(buf, sizeof(buf), fmt, lib, lang, ext); assert(cnt != -1); - if ((size_t)cnt <= sizeof(buf)) { + if ((size_t)cnt < sizeof(buf)) { path = (const char *)buf; } else if (!(file = malloc((size_t)cnt+1))) { return -1; From 709f95e7ce9f5d0ed3416fdc590912a0747dec0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Bollo?= Date: Tue, 14 Sep 2021 11:26:49 +0200 Subject: [PATCH 10/37] Prints diagnostic when plugin fails to load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A message is emitted to stderr when either the plugin can not be loaded or the symbol 'generate' can't be located in the loaded plugin. Logging to sdterr is in wait of some better integration to some other logging system. Signed-off-by: José Bollo --- src/tools/idlc/src/plugin.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/tools/idlc/src/plugin.c b/src/tools/idlc/src/plugin.c index 52c4a4ecfc..d10c88cee1 100644 --- a/src/tools/idlc/src/plugin.c +++ b/src/tools/idlc/src/plugin.c @@ -64,6 +64,28 @@ static void *loadsym(void *handle, const char *symbol) #endif } +static void liberror(char *buffer, size_t bufferlen) +{ + assert(buffer != NULL); + assert(bufferlen > 0); +#if WIN32 + DWORD error = GetLastError(); + (void)FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, + (DWORD)error, + 0, + (LPTSTR)buffer, + (DWORD)(bufferlen - 1), + NULL); + SetLastError(error); +#else + strncpy(buffer, dlerror(), bufferlen - 1); +#endif + buffer[bufferlen - 1] = 0; /* ensure final zero in all cases */ +} + extern int idlc_generate(const idl_pstate_t *pstate); int32_t @@ -105,6 +127,7 @@ idlc_load_generator(idlc_generator_plugin_t *plugin, const char *lang) } } + /* open the library */ if ((handle = openlib(path)) || (lang != path && (handle = openlib(lang)))) { generate = loadsym(handle, "generate"); if (generate) { @@ -113,9 +136,15 @@ idlc_load_generator(idlc_generator_plugin_t *plugin, const char *lang) plugin->generator_options = loadsym(handle, "generator_options"); plugin->generator_annotations = loadsym(handle, "generator_annotations"); } else { + fprintf(stderr, "Symbol 'generate' not found in %s\n", lang != path ? lang : path); closelib(handle); } } + else { + char errmsg[300]; + liberror(errmsg, sizeof(errmsg)); + fprintf(stderr, "Cannot load generator %s: %s\n", lang != path ? lang : path, errmsg); + } if (file) { free(file); From 22f70f1070ca5e36cd1faae59893695d363a4d74 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 21 Sep 2021 18:47:13 +0200 Subject: [PATCH 11/37] Update quality declaration Signed-off-by: Erik Boasson --- CYCLONEDDS_QUALITY_DECLARATION.md | 63 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/CYCLONEDDS_QUALITY_DECLARATION.md b/CYCLONEDDS_QUALITY_DECLARATION.md index 1a8581b017..6b5603bd39 100644 --- a/CYCLONEDDS_QUALITY_DECLARATION.md +++ b/CYCLONEDDS_QUALITY_DECLARATION.md @@ -1,8 +1,8 @@ -This document is a declaration of software quality for the [Eclipse Cyclone DDS](https://github.com/eclipse-cyclonedds/cyclonedds) (hereafter simply "Cyclone DDS") project, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html). +This document is a declaration of software quality for the [Eclipse Cyclone DDS](https://github.com/eclipse-cyclonedds/cyclonedds) (hereafter simply "Cyclone DDS") project, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html). This quality declaration is therefore specific to use in [ROS 2](https://index.ros.org/doc/ros2/)-based systems. # Cyclone DDS Quality Declaration -Cyclone DDS meets all the requirements of **Quality Level 3** category. +Cyclone DDS meets all the requirements of **Quality Level 2** category. The requirements for the various quality level categories are defined by [REP-2004](https://www.ros.org/reps/rep-2004.html). The rationale, notes and caveats for this claim are provided by the remainder of this document. @@ -37,19 +37,21 @@ The change history can be found in the [CHANGELOG](https://github.com/eclipse-cy Symbols starting with `dds_` or `DDS_` and that are accessible after including only the top-level `dds.h` file, unless explicitly stated otherwise in a documentation comment, constitute the Public API. -Definitions available in installed include files that are outside this definitions are either internal or part of an Evolving API that is expected to eventually become part of the Public API. -The distinction between Evolving APIs and internal definitions is currently not well-defined. +Definitions available in installed include files that are outside this definitions are either internal or part of an Evolving API that is expected to eventually become part of the Public API. Internal definitions are deliberately included in the install: the project chooses not to artifically limit users of Cyclone DDS to the Public or Evolving APIs. In the source repository, these header files reside with the modules that make up Cyclone DDS. ### API Stability Policy [1.iv] -Cyclone DDS provides Public API stability for PATCH and MINOR releases. -Cyclone DDS strives to provide Public API stability for MAJOR releases. -Cyclone DDS does not guarantee Public API stability for MAJOR releases. +For the Public API: +* Cyclone DDS provides Public API stability for PATCH and MINOR releases. +* Cyclone DDS strives to provide Public API stability for MAJOR releases. +* Cyclone DDS does not guarantee Public API stability for MAJOR releases. -Cyclone DDS provides Evolving API stability for PATCH releases and strives to provide Evolving API stability for MINOR releases. -Cyclone DDS does not guarantee Evolving API stability for MINOR and MAJOR releases. +For the Evolving API: +* Cyclone DDS provides Evolving API stability for PATCH releases. +* Cyclone DDS strives to provide Evolving API stability for MINOR releases. +* Cyclone DDS does not guarantee Evolving API stability for MINOR and MAJOR releases. The RMW interface is what ROS 2 deals with, and for a variety of reasons it may be decided to rely on unstable interfaces (or even implementation details), to better support ROS 2's design decisions that do not fit so well with DDS. Given ROS 2's importance to Cyclone DDS the Public API is expected to eventually cover all of ROS 2's needs, but without a defined time-line for that to happen. @@ -69,7 +71,7 @@ Cyclone DDS does not guarantee ABI stability for MINOR or MAJOR releases. ROS 2 users do not interact directly with Cyclone DDS and the mapping of the RMW interface to the Cyclone DDS APIs provided by the `rmw_cyclonedds` package hides any API or ABI changes from ROS 2 users. -Based on the ABI Stability Policy, Cyclone DDS PATCH releases can be accepted as updates within a Released ROS Distribution without also requiring an update to the `rmw_cyclonedds` package. +Based on the ABI Stability Policy, Cyclone DDS PATCH releases can be accepted as updates within a Released ROS Distribution. MINOR releases can likely be accepted as updates after assessing the binary compatibility. Cyclone DDS MINOR and MAJOR releases can, at least in principle, be accepted as updates within a Released ROS Distribution if the update is accompanied by an update of the `rmw_cyclonedds` package. ## Change Control [2] @@ -93,20 +95,21 @@ Eclipse projects furthermore require that an [Eclipse Contributor Agreement](htt ### Peer Review Policy [2.iii] -All pull requests must pass peer-review except when no-one is able to provide a review for a PR introduced by a Committer. +All pull requests must pass peer-review except when no-one is able to provide a review for a PR introduced by a Committer. The exception exists solely as an escape hatch if no review can be obtained within a reasonable time frame while there is an urgent need for the change introduced by the PR. Check [Eclipse Developer Process](https://www.eclipse.org/projects/dev_process/) for additional information. ### Continuous Integration [2.iv] Pull requests are required to pass all tests in the CI system prior to merging, unless Committers consider there is sufficient evidence that a failure is the result of a mishap unrelated to the change. -Cyclone DDS CI results are [public](https://dev.azure.com/eclipse-cyclonedds/cyclonedds/_build) and cover x64 platforms running Linux, macOS and Windows: +Cyclone DDS CI results are [public](https://dev.azure.com/eclipse-cyclonedds/cyclonedds/_build) and cover x64 and x86 platforms running Linux, macOS and Windows: - Ubuntu 20.04 with gcc 10 -- Ubuntu 18.04 with gcc 10 - Ubuntu 18.04 with gcc 7 - Ubuntu 20.04 with clang 10 - macOS 10.15 with clang 12 +- macOS 10.15 with clang 12 while targeting macOS 10.12 - Windows Server 2019 with Visual Studio 2019 +- Windows Server 2019 with gcc 10 (mingw) These are run with a mixture of debug, debug-with-address sanitizer and release builds. @@ -120,22 +123,18 @@ All pull requests must resolve related documentation changes before merging. ### Feature Documentation [3.i] -The project documentation does not include a high-level overview of the features and concepts. -These closely follow the [OMG DDS specification](https://www.omg.org/spec/DDS/1.4/PDF) which provides an accessible description. +The project documentation includes a getting started that introduces the high-level concepts, but it generally prefers to instead refer to the [OMG DDS specification](https://www.omg.org/spec/DDS/1.4/PDF) for an accessible and full description of the concepts and high-level features. -Some components can be enabled/disabled at compile-time through compilation options from the CMake files (e.g., DDS Security support). -The exact set is not well-documented. -Some other features are included/excluded at build time based on the features provided by the target platform (e.g., source-specific multicasting, DNS support to allow hostnames to be used in the configuration). -These are also not well-documented. +Some components can be enabled/disabled at compile-time through compilation options from the CMake files (e.g., DDS Security support). These are done with CMake options. + +Some other features are included/excluded at build time based on the features provided by the target platform (e.g., source-specific multicasting, DNS support to allow hostnames to be used in the configuration). All features are available on the tier 1 platforms, the ability to exclude them is needed for embedded platforms such as FreeRTOS. ### Public API Documentation [3.ii] -Reference information for the Public API is provided in the form of Doxygen comments. +Reference information for the Public API is provided in the form of Doxygen comments. Generated documentation is provided [online](https://cyclonedds.io). Configuration settings are documented in the source, with auto-generated [XSD files](https://github.com/eclipse-cyclonedds/cyclonedds/blob/master/etc/cyclonedds.xsd) and [markdown files](https://github.com/eclipse-cyclonedds/cyclonedds/blob/master/docs/manual/options.md) committed in the repository and linked from the front page. [Background information](https://github.com/eclipse-cyclonedds/cyclonedds/blob/master/docs/manual/config.rst) on configuration settings is also provided. -Generated documentation for the API is available in the [PDF document](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/pdf/CycloneDDS-0.1.0.pdf) linked in the project README. - ### License [3.iii] The license for Cyclone DDS is the Eclipse Public License 2.0 and the Eclipse Distribution License 1.0, and all of the code includes a header stating so. @@ -149,10 +148,14 @@ Details can also be found in the included [`NOTICE`](https://github.com/eclipse- The Cyclone DDS documentation includes a [policy](https://github.com/eclipse-cyclonedds/cyclonedds/blob/master/NOTICE.md#copyright) regarding content copyright, each of the source files containing code include a copyright statement with the license information in the file's header. +### Lists and Peer Review [3.v.c] + +This section is not applicable to a non-ROS project. + ## Testing [4] -Some directories within the Cyclone DDS source tree contain subdirectories for test code. -In all, the test code appears to comprise approximately 25% of the codebase. +Cyclone DDS source tree includes subdirectories for test code. +In all, the test code comprises approximately 25% of the codebase. ### Feature Testing [4.i] @@ -160,16 +163,14 @@ Each feature in Cyclone DDS has corresponding tests which simulate typical usage New features are required to have tests before being added. A substantial amount of the tests found throughout the source tree verify functionality of various features of Cyclone DDS. -However the lack of a complete feature list (see section [3.i]) makes it difficult to analyze the breadth of the tests. ### Public API Testing [4.ii] Each part of the public API has tests, and new additions or changes to the public API require tests before being added. The tests aim to cover both typical usage and corner cases. There are some tests throughout the Cyclone DDS source tree which specifically target the public API. -In principle the entire interface does get tested, and in reality it is pretty close. -Current lack of analysis of which parts of the code get hit by tests do make it hard to measure the extent of the tests. +There is no automated tracking of correlation between tests and API functionality. On the basis of a manual assessment conducted by the project, the overall number of tests and the number of reported issues, it is fair to conclude that the Public API is well-covered. In continuous integration, address sanitizer is enabled for some of the test matrix. Address sanitizer errors result in CI failure. @@ -193,12 +194,8 @@ We suggest and would like to assist Open Robotics to move all performance testin `rmw_cyclonedds` uses and passes all the ROS2 standard linters and static analysis tools for a C++ package as described in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#linters-and-static-analysis). Passing implies there are no linter/static errors when testing against CI of supported platforms. -Cyclone DDS has automated daily [Synopsys Coverity static code analysis](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html) with public results that can be seen [here](https://scan.coverity.com/projects/eclipse-cyclonedds-cyclonedds). -Cyclone DDS defect density is 0.05 per 1,000 lines of code as of Aug 11th 2020. -Omitting the Java idlc which is **not** used by ROS 2 gives 0.03 per 1,000 lines of code. -For comparison the average defect density of open source software projects of similar size is 0.5 per 1,000 lines of code. - -There are no linters enabled for the Cyclone DDS repository. +Cyclone DDS has automated [Synopsys Coverity static code analysis](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html) with public results that can be seen [here](https://scan.coverity.com/projects/eclipse-cyclonedds-cyclonedds). +Cyclone DDS has no outstanding defects as of 20-09-2021 on 240k lines analyzed. For comparison the average defect density of open source software projects of similar size is 0.5 per 1,000 lines of code. Coding style is considered and enforced in the review of all Cyclone DDS pull requests. Contributors are regularly asked to rewrite or reformat their code contributions before pull requests are accepted. From 22baacb4757bdfc1309cee45f4489b1a1d0c440f Mon Sep 17 00:00:00 2001 From: Martijn Reicher Date: Fri, 24 Sep 2021 11:31:44 +0200 Subject: [PATCH 12/37] Fix bug in tokenizing scoped names - The parser was not proceeding correctly in the case of the state being IDL_SCAN_ANNOTATION_APPL_SCOPED_NAME Signed-off-by: Martijn Reicher --- src/idl/src/scanner.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/idl/src/scanner.c b/src/idl/src/scanner.c index 9068d950df..35a5c1264c 100644 --- a/src/idl/src/scanner.c +++ b/src/idl/src/scanner.c @@ -753,6 +753,8 @@ tokenize( /* annotation names cannot be keywords, i.e. "@default" */ if (pstate->scanner.state == IDL_SCAN_ANNOTATION_APPL_NAME) goto identifier; + if (pstate->scanner.state == IDL_SCAN_ANNOTATION_APPL_SCOPED_NAME) + goto identifier; if (pstate->scanner.state == IDL_SCAN_ANNOTATION_NAME) goto identifier; if ((code = idl_iskeyword(pstate, str, !(pstate->flags & IDL_FLAG_CASE_SENSITIVE)))) From 00c6688348e12d67201599124e1517ff4936307d Mon Sep 17 00:00:00 2001 From: Martijn Reicher Date: Fri, 24 Sep 2021 11:33:38 +0200 Subject: [PATCH 13/37] Fix bug in evaluating bool, char and string literals - The parser was setting the node mask to IDL_ANY in stead of the correct mask for bool, char and string literals Signed-off-by: Martijn Reicher --- src/idl/src/expression.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/idl/src/expression.c b/src/idl/src/expression.c index aa3f179584..785eec6c7e 100644 --- a/src/idl/src/expression.c +++ b/src/idl/src/expression.c @@ -759,7 +759,7 @@ idl_evaluate( } } - if ((ret = idl_create_literal(pstate, idl_location(const_expr), type, nodep))) + if ((ret = idl_create_literal(pstate, idl_location(const_expr), implicit, nodep))) return ret; (*((idl_literal_t **)nodep))->value = temporary.value; done: From d1a34938ee5ca1e72a4709b27b0a5744df713a32 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 24 Sep 2021 13:43:11 +0200 Subject: [PATCH 14/37] Replace Codecov by Azure Pipelines Code Coverage Signed-off-by: Jeroen Koekkoek --- .azure/codecov.yml | 78 ---------------- .azure/templates/build-test.yml | 18 ++++ CMakeLists.txt | 1 - README.md | 2 +- azure-pipelines.yml | 1 + cmake/Modules/Codecov.cmake | 45 ---------- cmake/Modules/Codecov/codecov.cmake | 135 ---------------------------- 7 files changed, 20 insertions(+), 260 deletions(-) delete mode 100644 .azure/codecov.yml delete mode 100644 cmake/Modules/Codecov.cmake delete mode 100644 cmake/Modules/Codecov/codecov.cmake diff --git a/.azure/codecov.yml b/.azure/codecov.yml deleted file mode 100644 index c8be00e936..0000000000 --- a/.azure/codecov.yml +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright(c) 2021 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# -# Azure Pipeline specifically for building and submitting to Codecov -# - -trigger: none -pr: none - -schedules: - - cron: "0 12 * * 0" - branches: - include: [ master ] - always: false - -strategy: - matrix: - 'Ubuntu 20.04 LTS with GCC 10 (Debug, x86_64)': - image: ubuntu-20.04 - cc: gcc-10 - coverage: on - -pool: - vmImage: $(image) - -steps: - - template: /.azure/templates/build-test.yml - - bash: | - set -e -x - cd build - slug=$(echo "${BUILD_REPOSITORY_URI}" | sed -nE 's#.*/([^/]+/[^\]+)#\1#p') - commit="${BUILD_SOURCEVERSION}" - if [ -n "$pr" ] && [ "$pr" != false ]; then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; then - mc=$(echo "$mc" | cut -d ' ' -f2) - commit=$mc - fi - fi - query=$(curl -Gso /dev/null -w "%{url_effective}" "" \ - --data-urlencode "package=cmake-codecov.io" \ - --data-urlencode "token=${token}" \ - --data-urlencode "branch=${BUILD_SOURCEBRANCH#/refs/heads/}" \ - --data-urlencode "commit=${commit}" \ - --data-urlencode "build=${BUILD_BUILDNUMBER}" \ - --data-urlencode "build_url=${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECT}/_build/results?buildId=${BUILD_BUILDID}" \ - --data-urlencode "tag=" \ - --data-urlencode "slug=${slug}" \ - --data-urlencode "service=azure_pipelines" \ - --data-urlencode "flags=" \ - --data-urlencode "pr=${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER:-$SYSTEM_PULLREQUEST_PULLREQUESTID}" \ - --data-urlencode "job=${BUILD_BUILDID}" \ - --data-urlencode "project=${SYSTEM_TEAMPROJECT}" \ - --data-urlencode "server_uri=${SYSTEM_TEAMFOUNDATIONSERVERURI}" \ - 2>/dev/null | cut -c 3- | sed -e 's/%0A//') - cmake --build . --target codecov - code=$(curl -X POST -w "%{http_code}" \ - --data-binary @"codecov.tar.gz" \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'Content-Type: text/plain' \ - -H 'Content-Encoding: gzip' \ - -H 'X-Content-Encoding: gzip' \ - -H 'Accept: text/plain' \ - "https://codecov.io/upload/v2?$query") - [[ "${code}" =~ "success" ]] || (echo "cURL exited with ${code}" 1>&2 && exit 1) - name: submit_to_codecov - env: - token: $(CODECOV_TOKEN) diff --git a/.azure/templates/build-test.yml b/.azure/templates/build-test.yml index 3dc55f6438..065eabc0b9 100644 --- a/.azure/templates/build-test.yml +++ b/.azure/templates/build-test.yml @@ -71,6 +71,11 @@ steps: path: $(pip_cache) name: cache_pip - template: /.azure/templates/install-conan.yml + - bash: | + set -e -x + pip install gcovr --user --upgrade + condition: eq(variables['coverage'], 'on') + name: install_gcovr - bash: | set -e -x if [[ "${ICEORYX}" = 'on' ]] ; then @@ -126,3 +131,16 @@ steps: ${GENERATOR:+-G} "${GENERATOR}" -A "${PLATFORM}" -T "${TOOLSET}" "${INSTALLPREFIX}/share/CycloneDDS/examples/helloworld" cmake --build . --config ${BUILD_TYPE} -- ${BUILD_TOOL_OPTIONS} name: test + - bash: | + set -e -x + cd build + cmake --build . --config ${BUILD_TYPE} --target gcov -- ${BUILD_TOOL_OPTIONS} + gcovr --exclude '.*/tests/.*' --root "${BUILD_SOURCESDIRECTORY}" --xml-pretty --output coverage.xml . + condition: eq(variables['coverage'], 'on') + name: generate_code_coverage + - task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: 'Cobertura' + summaryFileLocation: $(Build.SourcesDirectory)/build/coverage.xml + condition: eq(variables['coverage'], 'on') + name: publish_code_coverage diff --git a/CMakeLists.txt b/CMakeLists.txt index 76c0dc9334..414e8915c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,7 +228,6 @@ if(SANITIZER) endif() find_package(codecov) -include(Codecov) set(MEMORYCHECK_COMMAND_OPTIONS "--track-origins=yes --leak-check=full --trace-children=yes --child-silent-after-fork=yes --xml=yes --xml-file=TestResultValgrind_%p.xml --tool=memcheck --show-reachable=yes --leak-resolution=high") # By default building the testing tree is enabled by including CTest, but diff --git a/README.md b/README.md index 2af58d37b4..15199cf2f7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Build Status](https://dev.azure.com/eclipse-cyclonedds/cyclonedds/_apis/build/status/Pull%20requests?branchName=master)](https://dev.azure.com/eclipse-cyclonedds/cyclonedds/_build/latest?definitionId=4&branchName=master) [![Coverity Status](https://scan.coverity.com/projects/19078/badge.svg)](https://scan.coverity.com/projects/eclipse-cyclonedds-cyclonedds) -[![Codecov](https://codecov.io/gh/eclipse-cyclonedds/cyclonedds/branch/master/graphs/badge.svg?branch=master)](https://codecov.io/github/eclipse-cyclonedds/cyclonedds?branch=master) +[![Coverage](https://img.shields.io/azure-devops/coverage/eclipse-cyclonedds/cyclonedds/4/master)](https://dev.azure.com/eclipse-cyclonedds/cyclonedds/_build/latest?definitionId=4&branchName=master) [![License](https://img.shields.io/badge/License-EPL%202.0-blue)](https://choosealicense.com/licenses/epl-2.0/) [![License](https://img.shields.io/badge/License-EDL%201.0-blue)](https://choosealicense.com/licenses/edl-1.0/) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0b860b0730..0937a914c7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -41,6 +41,7 @@ strategy: cc: gcc-10 'Ubuntu 18.04 LTS with GCC 7 (Debug, x86_64)': image: ubuntu-18.04 + coverage: on conanfile: conanfile102.txt cc: gcc-7 'Ubuntu 20.04 LTS with Clang 10 (Debug, x86_64)': diff --git a/cmake/Modules/Codecov.cmake b/cmake/Modules/Codecov.cmake deleted file mode 100644 index 7ddce68a04..0000000000 --- a/cmake/Modules/Codecov.cmake +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright(c) 2020 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# This module is meant to be used in conjuntion with CMake-codecov -# https://github.com/RWTH-HPC/CMake-codecov -# -# A codecov target is added if ENABLE_COVERAGE is on. -# Generate a codecov.io submission file with cmake --build . --target codecov. -# Submit the file to codecov.io by putting the proper commands in .travis.yml. -# See https://codecov.io/bash for details. - -if(ENABLE_COVERAGE) - if(NOT TARGET gcov) - add_custom_target(gcov) - endif() - if(NOT TARGET codecov) - set(CODECOV_FILE codecov.dump) - set(CODECOV_ARCHIVE codecov.tar.gz) - add_custom_target(codecov) - add_dependencies(codecov gcov) - add_custom_command( - TARGET codecov - POST_BUILD - BYPRODUCTS - "${CMAKE_BINARY_DIR}/${CODECOV_FILE}" - "${CMAKE_BINARY_DIR}/${CODECOV_ARCHIVE}" - COMMAND ${CMAKE_COMMAND} ARGS - -DPROJECT_ROOT="${CMAKE_SOURCE_DIR}" - -DCODECOV_FILE="${CODECOV_FILE}" - -P ${CMAKE_CURRENT_LIST_DIR}/Codecov/codecov.cmake - COMMAND ${CMAKE_COMMAND} ARGS - -E tar czf ${CODECOV_ARCHIVE} -- ${CODECOV_FILE} - COMMENT "Generating ${CODECOV_ARCHIVE}" - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) - endif() -endif() diff --git a/cmake/Modules/Codecov/codecov.cmake b/cmake/Modules/Codecov/codecov.cmake deleted file mode 100644 index 598630e6c4..0000000000 --- a/cmake/Modules/Codecov/codecov.cmake +++ /dev/null @@ -1,135 +0,0 @@ -# -# Copyright(c) 2020 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# CMake script to produce a codecov.io submission file. -# Should be compatible with https://codecov.io/bash. - -if(NOT PROJECT_ROOT) - message(FATAL_ERROR "PROJECT_ROOT is not set") -endif() - -if(NOT CODECOV_FILE) - message(FATAL_ERROR "CODECOV_FILE is not set") -endif() - -function(read_adjustments ROOT SOURCEFILE ADJUSTMENTS) - file(READ "${SOURCEFILE}" _source) - # replace semicolons by colons - string(REPLACE ";" ":" _source "${_source}") - # replace newlines by semicolons - # space is inserted to ensure blank lines are picked up - string(REPLACE "\n" " ;" _source "${_source}") - - # include matching lines in adjustments - set(_line_number 0) - foreach(_line ${_source}) - math(EXPR _line_number "${_line_number} + 1") - # empty_line='^[[:space:]]*$' - if(_line MATCHES "^[ \t]*$") - list(APPEND _adjustments ${_line_number}) - # syntax_bracket='^[[:space:]]*[\{\}][[:space:]]*(//.*)?$' - elseif(_line MATCHES "^[ \t]*[{}][ \t]*(//.*)?") - list(APPEND _adjustments ${_line_number}) - # //LCOV_EXCL - elseif(_line MATCHES "// LCOV_EXCL") - list(APPEND _adjustments ${_line_number}) - endif() - endforeach() - - if(_adjustments) - string(REPLACE ";" "," _adjustments "${_adjustments}") - set(${ADJUSTMENTS} "${SOURCEFILE}:${_adjustments}\n" PARENT_SCOPE) - endif() -endfunction() - -function(read_and_reduce_gcov ROOT GCOVFILE SOURCEFILE GCOV) - file(READ "${GCOVFILE}" _gcov) - # grab first line - string(REGEX MATCH "^[^\n]*" _source "${_gcov}") - - # reduce gcov - # 1. remove source code - # 2. remove ending bracket lines - # 3. remove whitespace - string(REGEX REPLACE " *([^ \n:]*): *([^ \n:]*):?[^\n]*" "\\1:\\2:" _gcov "${_gcov}") - # 4. remove contextual lines - string(REGEX REPLACE "-+[^\n]*\n" "" _gcov "${_gcov}") - # 5. remove function names - - string(REPLACE "${ROOT}" "" _path "${GCOVFILE}") - string(REGEX REPLACE "^/+" "" _path "${_path}") - string(PREPEND _gcov "# path=${_path}.reduced\n${_source}\n") - string(APPEND _gcov "<<<<<< EOF\n") - - # capture source file - string(REGEX REPLACE "^.*:Source:(.*)$" "\\1" _source "${_source}") - - set(${SOURCEFILE} "${_source}" PARENT_SCOPE) - set(${GCOV} "${_gcov}" PARENT_SCOPE) -endfunction() - -set(project_dir "${PROJECT_ROOT}") -set(build_dir "${CMAKE_CURRENT_BINARY_DIR}") - -# Codecov supports .codecov.yml files to configure the service. The location -# of the first .codecov.yml found by the bash uploader is in included in the -# the list of files submitted to the service. -file(GLOB_RECURSE yaml_files RELATIVE "${PROJECT_ROOT}" "${PROJECT_ROOT}/*codecov.y*ml") -if(yaml_files) - list(GET yaml_files 0 yaml_file) -endif() - -set(network_block "${yaml_file}\n") -set(gcov_block "") -set(adjustments_block "") - -# Codecov uses "git ls-files" and falls back to find, but having no -# dependencies is preferred (for now). Globbing rules are very likely to -# produce the same result -file(GLOB_RECURSE source_files "${PROJECT_ROOT}/*.[hH]" - "${PROJECT_ROOT}/*.[Cc]" - "${PROJECT_ROOT}/*.[Hh][Pp][Pp]" - "${PROJECT_ROOT}/*.[Cc][Pp][Pp]" - "${PROJECT_ROOT}/*.[Cc][Xx][Xx]") - -file(GLOB_RECURSE gcov_files "${CMAKE_CURRENT_BINARY_DIR}/*.gcov") -foreach(gcov_file ${gcov_files}) - read_and_reduce_gcov("${PROJECT_ROOT}" "${gcov_file}" source_file gcov) - list(APPEND source_files "${source_file}") - string(APPEND gcov_block "${gcov}") -endforeach() - -list(REMOVE_DUPLICATES source_files) -foreach(source_file ${source_files}) - # ignore any files located in the build directory - string(FIND "${source_file}" "${build_dir}/" in_build_dir) - if(in_build_dir GREATER_EQUAL 0) - continue() - endif() - # ignore paths with /CMakeFiles/ - if(source_file MATCHES "/CMakeFiles/") - continue() - endif() - read_adjustments("${PROJECT_ROOT}" "${source_file}" adjustments) - string(APPEND adjustments_block "${adjustments}") - string(REPLACE "${PROJECT_ROOT}" "" source_file "${source_file}") - string(REGEX REPLACE "^/+" "" source_file "${source_file}") - string(APPEND network_block "${source_file}\n") -endforeach() - -string(PREPEND adjustments_block "# path=fixes\n") -string(APPEND adjustments_block "<<<<<< EOF") -string(APPEND network_block "<<<<<< network\n") - -file(WRITE ${CODECOV_FILE} "${network_block}") -file(APPEND ${CODECOV_FILE} "${gcov_block}") -file(APPEND ${CODECOV_FILE} "${adjustments_block}") From 34957ecf92be39157d206f92866c7e9b4c9b55ad Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 23 Sep 2021 17:51:54 +0200 Subject: [PATCH 15/37] Fix use-after-free if union creation fails Signed-off-by: Dennis Potman --- src/idl/src/parser.y | 23 ++++++++++++++--------- src/idl/tests/union.c | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/idl/src/parser.y b/src/idl/src/parser.y index 6bc96ca527..310e7ff8c8 100644 --- a/src/idl/src/parser.y +++ b/src/idl/src/parser.y @@ -185,6 +185,7 @@ void idl_yypstate_delete_stack(idl_yypstate *yyps); %type struct_def struct_header %type members member struct_body %type union_def union_header +%type switch_header %type <_case> switch_body case element_spec %type case_labels case_label %type enum_def @@ -215,6 +216,7 @@ void idl_yypstate_delete_stack(idl_yypstate *yyps); <_case> + %token IDL_TOKEN_LINE_COMMENT %token IDL_TOKEN_COMMENT @@ -754,15 +756,18 @@ union_def: ; union_header: - "union" identifier "switch" '(' annotations switch_type_spec - { idl_switch_type_spec_t *node = NULL; - TRY(idl_create_switch_type_spec(pstate, &@6, $6, &node)); - TRY_EXCEPT(idl_annotate(pstate, node, $5), idl_delete_node(node)); - $$ = node; - } - ')' - { idl_switch_type_spec_t *node = $7; - TRY(idl_create_union(pstate, LOC(@1.first, @8.last), $2, node, &$$)); + "union" identifier switch_header + { TRY(idl_create_union(pstate, LOC(@1.first, @3.last), $2, $3, &$$)); } + ; + +switch_header: + "switch" '(' annotations switch_type_spec ')' + { /* switch_header action is a separate non-terminal, as opposed to a + mid-rule action, to avoid freeing the type specifier twice (once + through destruction of the type-spec and once through destruction + of the switch-type-spec) if union creation fails */ + TRY(idl_create_switch_type_spec(pstate, &@4, $4, &$$)); + TRY_EXCEPT(idl_annotate(pstate, $$, $3), idl_delete_node($$)); } ; diff --git a/src/idl/tests/union.c b/src/idl/tests/union.c index 6ed0d29bb8..bd722af1f1 100644 --- a/src/idl/tests/union.c +++ b/src/idl/tests/union.c @@ -36,6 +36,21 @@ CU_Test(idl_union, no_case) idl_delete_pstate(pstate); } +CU_Test(idl_union, name_clash) +{ + idl_retcode_t ret; + idl_pstate_t *pstate = NULL; + + const char str[] = "union u switch (long) { case 1: char c; };\n" + "union u switch (long) { case 1: char c; };"; + ret = idl_create_pstate(0u, NULL, &pstate); + CU_ASSERT_EQUAL_FATAL(ret, IDL_RETCODE_OK); + CU_ASSERT_PTR_NOT_NULL_FATAL(pstate); + ret = idl_parse_string(pstate, str); + CU_ASSERT_EQUAL(ret, IDL_RETCODE_SEMANTIC_ERROR); + idl_delete_pstate(pstate); +} + CU_Test(idl_union, single_case) { idl_retcode_t ret; From ac2c563de884aceb999f416e5610e703b1766599 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 23 Sep 2021 18:11:24 +0200 Subject: [PATCH 16/37] Fix use-after-free if enum is used in multiple unions Case label destructors deleted the const-expr as opposed to unreferencing it causing a use-after-free if the same enum was used in more than one union. Fixes #946. Signed-off-by: Jeroen Koekkoek --- src/idl/src/tree.c | 2 +- src/idl/tests/union.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/idl/src/tree.c b/src/idl/src/tree.c index 94ff828f27..239c14ce6e 100644 --- a/src/idl/src/tree.c +++ b/src/idl/src/tree.c @@ -1877,7 +1877,7 @@ bool idl_is_case_label(const void *ptr) static void delete_case_label(void *ptr) { idl_case_label_t *node = ptr; - idl_delete_node(node->const_expr); + delete_const_expr(node, node->const_expr); free(node); } diff --git a/src/idl/tests/union.c b/src/idl/tests/union.c index bd722af1f1..e51af44ed0 100644 --- a/src/idl/tests/union.c +++ b/src/idl/tests/union.c @@ -576,3 +576,20 @@ CU_Test(idl_union, default_discriminator_enum) CU_ASSERT_PTR_NULL(pstate); idl_delete_pstate(pstate); } + +CU_Test(idl_union, two_unions_one_enum) +{ + idl_retcode_t ret; + idl_pstate_t *pstate = NULL; + + const char str[] = "enum aap { noot, mies };\n" + "union wim switch (aap) { case mies: double zus; };\n" + "union jet switch (aap) { case noot: double zus; };"; + + ret = idl_create_pstate(0u, NULL, &pstate); + CU_ASSERT_EQUAL_FATAL(ret, IDL_RETCODE_OK); + CU_ASSERT_PTR_NOT_NULL_FATAL(pstate); + ret = idl_parse_string(pstate, str); + CU_ASSERT_EQUAL(ret, IDL_RETCODE_OK); + idl_delete_pstate(pstate); +} From 92abf6ee9df651ce4613e51aa3a441f0b3436934 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Fri, 24 Sep 2021 16:25:19 +0200 Subject: [PATCH 17/37] Remove annotation_appl midrule action Destructors are not executed for untyped midrule actions because Bison does not know which destructor to run. annotation_appl nodes were not cleaned up if the annotation_appl could not be successfully finalized. Remove use of midrule actions in annotation_appl as some platforms still ship with Bison 3.0.4. Fixes #950. Signed-off-by: Jeroen Koekkoek --- src/idl/src/parser.y | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/idl/src/parser.y b/src/idl/src/parser.y index 310e7ff8c8..435257ea27 100644 --- a/src/idl/src/parser.y +++ b/src/idl/src/parser.y @@ -196,7 +196,7 @@ void idl_yypstate_delete_stack(idl_yypstate *yyps); %type const_dcl %type annotation_dcl annotation_header %type annotation_body annotation_member -%type annotations annotation_appl annotation_appls +%type annotations annotation_appl annotation_appls annotation_appl_header %type annotation_appl_params annotation_appl_keyword_param annotation_appl_keyword_params @@ -973,31 +973,35 @@ annotation_appls: ; annotation_appl: + annotation_appl_header annotation_appl_params + { if (pstate->parser.state != IDL_PARSE_UNKNOWN_ANNOTATION_APPL_PARAMS) + TRY(idl_finalize_annotation_appl(pstate, LOC(@1.first, @2.last), $1, $2)); + pstate->parser.state = IDL_PARSE; + pstate->annotation_scope = NULL; + $$ = $1; + } + ; + +annotation_appl_header: "@" { pstate->parser.state = IDL_PARSE_ANNOTATION_APPL; } annotation_appl_name - { idl_annotation_appl_t *node = NULL; - const idl_annotation_t *annotation; + { const idl_annotation_t *annotation; const idl_declaration_t *declaration = idl_find_scoped_name(pstate, NULL, $3, IDL_FIND_ANNOTATION); pstate->annotations = true; /* register annotation occurence */ - if (!declaration) { - pstate->parser.state = IDL_PARSE_UNKNOWN_ANNOTATION_APPL_PARAMS; - } else { + + $$ = NULL; + if (declaration) { annotation = idl_reference_node((idl_node_t *)declaration->node); - TRY(idl_create_annotation_appl(pstate, LOC(@1.first, @3.last), annotation, &node)); + TRY(idl_create_annotation_appl(pstate, LOC(@1.first, @3.last), annotation, &$$)); pstate->parser.state = IDL_PARSE_ANNOTATION_APPL_PARAMS; pstate->annotation_scope = declaration->scope; + } else { + pstate->parser.state = IDL_PARSE_UNKNOWN_ANNOTATION_APPL_PARAMS; } - $$ = node; - } - annotation_appl_params - { if (pstate->parser.state != IDL_PARSE_UNKNOWN_ANNOTATION_APPL_PARAMS) - TRY(idl_finalize_annotation_appl(pstate, LOC(@1.first, @5.last), $4, $5)); - pstate->parser.state = IDL_PARSE; - pstate->annotation_scope = NULL; - $$ = $4; + idl_delete_scoped_name($3); } ; From e62a87afe438bb95d93d176e44df578dde5ac70b Mon Sep 17 00:00:00 2001 From: Thijs Miedema Date: Wed, 29 Sep 2021 10:26:34 +0200 Subject: [PATCH 18/37] Add python idl locator to idlc --- src/tools/idlc/src/plugin.c | 79 ++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/src/tools/idlc/src/plugin.c b/src/tools/idlc/src/plugin.c index d10c88cee1..4a16428180 100644 --- a/src/tools/idlc/src/plugin.c +++ b/src/tools/idlc/src/plugin.c @@ -21,6 +21,8 @@ static const char sep[] = "/\\"; static const char lib[] = ""; static const char ext[] = "dll"; +#define SUBPROCESS_POPEN _popen +#define SUBPROCESS_PCLOSE _pclose #else #include static const char sep[] = "/"; @@ -30,6 +32,8 @@ static const char ext[] = "dylib"; #else static const char ext[] = "so"; #endif +#define SUBPROCESS_POPEN popen +#define SUBPROCESS_PCLOSE pclose #endif #include "plugin.h" @@ -86,6 +90,63 @@ static void liberror(char *buffer, size_t bufferlen) buffer[bufferlen - 1] = 0; /* ensure final zero in all cases */ } +#define SUBPROCESS_PIPE_MEMORY_LIMIT 1024 * 1024 +static int run_library_locator(const char *command, char **out_output) { + size_t output_size = 0; + size_t output_pt = 0; + char *output = NULL; + FILE *pipe; + int ret = 0; + bool success = true; + int c; + + if ((pipe = SUBPROCESS_POPEN (command, "r")) == NULL) { + // broken-pipe + return -1; + } + + while ((c = fgetc(pipe)) != EOF) { + if (c == '\n' || c == '\r') { + break; + } + + if (output_pt == output_size) { + output_size += 128; + if (output_size > SUBPROCESS_PIPE_MEMORY_LIMIT) { + success = false; + break; + } + + char* new = (char*) realloc(output, output_size); + if (!new) { + success = false; + break; + } + output = new; + } + + output[output_pt++] = (char) c; + } + + ret = SUBPROCESS_PCLOSE (pipe); + + if (success && output != NULL && ret == 0) { + // ensure proper string termination (might be newline) + output[output_pt] = '\0'; + *out_output = output; + + return 0; + } + + // error + if (output) { + free(output); + } + + return -1; +} + + extern int idlc_generate(const idl_pstate_t *pstate); int32_t @@ -106,8 +167,24 @@ idlc_load_generator(idlc_generator_plugin_t *plugin, const char *lang) return 0; } + /* special case for python generator + The 'active' idlpy library is dependend on which python is active. Idlpy is installed + as part of the cyclonedds python package and it can very well be that multiple installations + are present on the system, by use of virtual environments, user installs and system installs. + Sadly activating a python distribution does not set a any library loading paths. However, + the python cyclonedds package has a __idlc__ module that prints the path when executed. The + 'python3' executable is always guaranteed to point to the active python so we always get the + correct idlpy library. + */ + if (idl_strcasecmp(lang, "py") == 0) { + if (run_library_locator("python3 -m cyclonedds.__idlc__", &file) != 0) { + return -1; + } + path = (const char*) file; + } + /* figure out if user passed library or language */ - if ((sep[0] && strchr(lang, sep[0])) || (sep[1] && strchr(lang, sep[1]))) { + else if ((sep[0] && strchr(lang, sep[0])) || (sep[1] && strchr(lang, sep[1]))) { path = lang; /* lang includes a directory separator, it is a path */ } else if (len > extlen && strcmp(lang + (len - extlen), ext) == 0) { path = lang; /* lang terminates with extension of plugins (libs), it is a path */ From 3c69a5cd77d63a1c85a0eebd604f67ba014fe6ad Mon Sep 17 00:00:00 2001 From: Thijs Miedema Date: Wed, 15 Sep 2021 11:08:52 +0200 Subject: [PATCH 19/37] MCPP: cmake changes to remove check_target_cpu. Since we are targeting 'C' as a language platform-specific macros are irrelevant for idlc, and this is a blocker for compiling mac universal binaries. --- cmake/Modules/CheckTargetCPU.c.in | 49 ---------------- cmake/Modules/CheckTargetCPU.cmake | 93 ------------------------------ src/tools/idlpp/CMakeLists.txt | 2 - src/tools/idlpp/src/configed.H.in | 2 +- 4 files changed, 1 insertion(+), 145 deletions(-) delete mode 100644 cmake/Modules/CheckTargetCPU.c.in delete mode 100644 cmake/Modules/CheckTargetCPU.cmake diff --git a/cmake/Modules/CheckTargetCPU.c.in b/cmake/Modules/CheckTargetCPU.c.in deleted file mode 100644 index 6c25744892..0000000000 --- a/cmake/Modules/CheckTargetCPU.c.in +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright(c) 2019 Jeroen Koekkoek - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -/* Simple source file to determine CPU architecture (CheckTypeSize.c.in from - CMake served as an example). Support for additional processor architectures - and/or compilers may be added in the future. A good source for predefined - macros is the Pre-defined Compiler Macros page on SourceForge: - https://sourceforge.net/projects/predef/ */ - -#if defined(__i386) || defined(_M_IX86) -# define CPU 'i','3','8','6' -#elif defined(__x86_64) || defined(_M_AMD64) -# define CPU 'x','8','6','_','6','4' -#elif defined(__ppc__) -# define CPU 'p','p','c' -#elif defined(__ppc64__) -# define CPU 'p','p','c','6','4' -#elif defined(__arm__) || defined(_M_ARM) -# define CPU 'a','r','m' -#elif defined(__aarch64__) || defined(_M_ARM64) -# define CPU 'a','a','r','c','h','6','4' -#endif - -#ifdef __CLASSIC_C__ -int main(argc, argv) int argc; char *argv[]; -#else -int main(int argc, char *argv[]) -#endif -{ - static const char cpu[] = {'I','N','F','O',':','c','p','u','[', -#ifdef CPU - CPU, -#else - 'u', 'n', 'k', 'n', 'o', 'w', 'n', -#endif - ']', '\0'}; - - return 0; -} - diff --git a/cmake/Modules/CheckTargetCPU.cmake b/cmake/Modules/CheckTargetCPU.cmake deleted file mode 100644 index 4c2e297dd7..0000000000 --- a/cmake/Modules/CheckTargetCPU.cmake +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright(c) 2019 Jeroen Koekkoek -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -get_filename_component(__check_target_cpu_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) - -include_guard(GLOBAL) - -function(__check_target_cpu_impl _var _lang) - if(_lang STREQUAL "C") - set(_src "${CMAKE_BINARY_DIR}/CheckTargetCPU/${_var}.c") - elseif(lang STREQUAL "CXX") - set(_src "${CMAKE_BINARY_DIR}/CheckTargetCPU/${_var}.cpp") - endif() - - set(_bin ${CMAKE_BINARY_DIR}/CheckTargetCPU/${_var}.bin) - configure_file(${__check_target_cpu_dir}/CheckTargetCPU.c.in ${_src} @ONLY) - try_compile(HAVE_${_var} ${CMAKE_BINARY_DIR} ${_src} - COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} - LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS} - LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} - CMAKE_FLAGS - "-DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}" - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}" - OUTPUT_VARIABLE _output - COPY_FILE ${_bin} - ) - - if(HAVE_${_var}) - # Fat binaries may be generated on macOS X and multiple, incompatible, - # occurrences of INFO:cpu[] may be found. - file(STRINGS ${_bin} _strs LIMIT_COUNT 10 REGEX "INFO:cpu") - set(_expr_cpu ".*INFO:cpu\\[([^]]+)\\]") - set(_first TRUE) - foreach(_info ${_strs}) - if(${_info} MATCHES "${_expr_cpu}") - set(_temp "${CMAKE_MATCH_1}") - if(_first) - set(_cpu "${_temp}") - elseif(NOT "${_cpu}" STREQUAL "${_temp}") - set(_mismatch TRUE) - endif() - set(_first FALSE) - endif() - endforeach() - - if(_mismatch) - message(SEND_ERROR "CHECK_TARGET_CPU found different results, consider setting CMAKE_OSX_ARCHITECTURES or CMAKE_TRY_COMPILE_OSX_ARCHITECTURES to one or no architecture !") - endif() - - if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Check target architecture - done") - endif() - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Determining target architecture passed with the following output:\n${_output}\n\n") - set(${_var} "${_cpu}" CACHE INTERNAL "CHECK_TARGET_CPU") - else() - if(NOT CMAKE_REQUIRED_QUIET) - message(STATUS "Check target architecture - failed") - endif() - file(READ ${_src} content) - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining target architecture failed with the following output:\n${_output}\n${_src}:\n${_content}\n\n") - set(${_var} "" CACHE INTERNAL "CHECK_TARGET_CPU: unknown") - endif() -endfunction() - -macro(CHECK_TARGET_CPU VARIABLE) - set(_opts) - set(_single_opts LANGUAGE) - set(_multi_opts) - cmake_parse_arguments(_opt "${_opts}" "${_single_opts}" "${_multi_opts}" ${ARGN}) - - if(NOT DEFINED _opt_LANGUAGE) - set(_lang "C") - elseif(NOT "x${_opt_LANGUAGE}" MATCHES "^x(C|CXX)$") - message(FATAL_ERROR "Unknown language:\n ${_opt_LANGUAGE}.\nSupported languages: C, CXX.\n") - else() - set(_lang "${_opt_LANGUAGE}") - endif() - - if(NOT DEFINED HAVE_${VARIABLE}) - __check_target_cpu_impl(${VARIABLE} ${_lang}) - endif() -endmacro() - diff --git a/src/tools/idlpp/CMakeLists.txt b/src/tools/idlpp/CMakeLists.txt index 0f101e5770..cca2b9ca98 100644 --- a/src/tools/idlpp/CMakeLists.txt +++ b/src/tools/idlpp/CMakeLists.txt @@ -16,7 +16,6 @@ endif() include(CheckIncludeFile) include(CheckSymbolExists) -include(CheckTargetCPU) include(CheckTypeSize) include(GenerateExportHeader) @@ -104,7 +103,6 @@ if(idlpp_system STREQUAL "SYS_FREEBSD") endif() endif() -check_target_cpu(idlpp_cpu) check_include_file(stdint.h idlpp_have_stdint_h) check_include_file(inttypes.h idlpp_have_inttypes_h) have_type("intmax_t" idlpp_have_intmax_t) diff --git a/src/tools/idlpp/src/configed.H.in b/src/tools/idlpp/src/configed.H.in index 1ed2def91a..16b084f021 100644 --- a/src/tools/idlpp/src/configed.H.in +++ b/src/tools/idlpp/src/configed.H.in @@ -38,7 +38,7 @@ compiled to language-specific sources, not machine code. */ /* Define the cpu-specific-macro. */ -#define CPU "@idlpp_cpu@" +#define CPU "" /* Define the target system. */ #define SYSTEM @idlpp_system@ From fdce92f92c92cf25cc2068a0053620f64e3bb960 Mon Sep 17 00:00:00 2001 From: Thijs Miedema Date: Fri, 17 Sep 2021 11:13:56 +0200 Subject: [PATCH 20/37] Enable building cross-platform with idlc/ddsconf --- CMakeLists.txt | 18 ++- .../idlc => cmake/Modules}/Generate.cmake | 19 ++- docs/CMakeLists.txt | 8 +- examples/CMakeLists.txt | 2 + src/CMakeLists.txt | 2 +- src/core/ddsi/CMakeLists.txt | 5 +- src/core/xtests/cdrtest/CMakeLists.txt | 2 +- src/tools/CMakeLists.txt | 8 +- src/tools/ddsconf/CMakeLists.txt | 48 +++++- src/tools/ddsperf/CMakeLists.txt | 4 +- src/tools/idlc/CMakeLists.txt | 147 +++++++++--------- src/tools/idlpp/CMakeLists.txt | 4 +- src/tools/idlpp/src/configed.H.in | 2 +- 13 files changed, 162 insertions(+), 107 deletions(-) rename {src/tools/idlc => cmake/Modules}/Generate.cmake (85%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 414e8915c4..8d04f699ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,12 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() +if(CMAKE_CROSSCOMPILING) + set(not_crosscompiling OFF) +else() + set(not_crosscompiling ON) +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. @@ -34,7 +40,9 @@ option(WERROR "Treat compiler warnings as errors" OFF) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules") -option(BUILD_IDLC "Build IDL preprocessor" ON) +option(BUILD_IDLC "Build IDL preprocessor" ${not_crosscompiling}) +option(BUILD_DDSCONF "Build DDSCONF buildtool" ${not_crosscompiling}) + set(CMAKE_C_STANDARD 99) if(CMAKE_SYSTEM_NAME STREQUAL "VxWorks") @@ -234,15 +242,11 @@ set(MEMORYCHECK_COMMAND_OPTIONS "--track-origins=yes --leak-check=full --trace-c # since not everybody has CUnit, and because it is not strictly required to # build the product itself, switch to off by default. option(BUILD_TESTING "Build the testing tree." OFF) + # Disable building examples by default because it is not strictly required. option(BUILD_EXAMPLES "Build examples." OFF) option(BUILD_DOCS "Build documentation." OFF) -if(CMAKE_CROSSCOMPILING) - set(not_crosscompiling OFF) -else() - set(not_crosscompiling ON) -endif() option(BUILD_SCHEMA "Build generated schema for configuration options." ${not_crosscompiling}) # Build all executables and libraries into the top-level /bin and /lib folders. @@ -299,7 +303,7 @@ install( COMPONENT dev) add_subdirectory(src) -if(BUILD_IDLC AND BUILD_EXAMPLES) +if(BUILD_EXAMPLES) add_subdirectory(examples) endif() diff --git a/src/tools/idlc/Generate.cmake b/cmake/Modules/Generate.cmake similarity index 85% rename from src/tools/idlc/Generate.cmake rename to cmake/Modules/Generate.cmake index 9b30769996..c5c0d678d4 100644 --- a/src/tools/idlc/Generate.cmake +++ b/cmake/Modules/Generate.cmake @@ -9,12 +9,27 @@ # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # + + function(IDLC_GENERATE) set(one_value_keywords TARGET) set(multi_value_keywords FILES FEATURES) cmake_parse_arguments( IDLC "" "${one_value_keywords}" "${multi_value_keywords}" "" ${ARGN}) + if (CMAKE_CROSSCOMPILING) + find_program(_idlc_executable idlc NO_CMAKE_FIND_ROOT_PATH REQUIRED) + + if (_idlc_executable) + set(_idlc_depends "") + else() + message(FATAL_ERROR "Cannot find idlc executable") + endif() + else() + set(_idlc_executable CycloneDDS::idlc) + set(_idlc_depends CycloneDDS::idlc) + endif() + if(NOT IDLC_TARGET AND NOT IDLC_FILES) # assume deprecated invocation: TARGET FILE [FILE..] list(GET IDLC_UNPARSED_ARGUMENTS 0 IDLC_TARGET) @@ -57,9 +72,9 @@ function(IDLC_GENERATE) list(APPEND _headers "${_header}") add_custom_command( OUTPUT "${_source}" "${_header}" - COMMAND CycloneDDS::idlc + COMMAND ${_idlc_executable} ARGS ${_file} ${IDLC_ARGS} - DEPENDS ${_files} CycloneDDS::idlc) + DEPENDS ${_files} ${_idlc_depends}) endforeach() add_custom_target("${_target}_generate" DEPENDS "${_sources}" "${_headers}") diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 624b31b9c9..dc12e08a20 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -19,11 +19,11 @@ set(options_md "${CMAKE_CURRENT_BINARY_DIR}/manual/options.md") if(BUILD_SCHEMA OR BUILD_DOCS) add_custom_command( OUTPUT "${cyclonedds_rnc}" "${cyclonedds_xsd}" "${options_md}" - COMMAND ddsconf ARGS -f rnc -o "${cyclonedds_rnc}" - COMMAND ddsconf ARGS -f xsd -o "${cyclonedds_xsd}" + COMMAND ddsconf-native ARGS -f rnc -o "${cyclonedds_rnc}" + COMMAND ddsconf-native ARGS -f xsd -o "${cyclonedds_xsd}" COMMAND ${CMAKE_COMMAND} -E make_directory manual - COMMAND ddsconf ARGS -f md -o "${options_md}" - DEPENDS ddsconf) + COMMAND ddsconf-native ARGS -f md -o "${options_md}" + DEPENDS ddsconf-native) add_custom_target( schema ALL DEPENDS "${cyclonedds_rnc}" "${cyclonedds_xsd}" "${options_md}") endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d592001adc..2e50f3ebb4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -11,6 +11,8 @@ # set(CMAKE_INSTALL_EXAMPLESDIR "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/examples") +include("${CMAKE_SOURCE_DIR}/cmake/Modules/Generate.cmake") + install( FILES helloworld/HelloWorldData.idl diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c193c578bf..e8ba113eaf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -115,7 +115,7 @@ configure_file(features.h.in "${CMAKE_CURRENT_BINARY_DIR}/core/include/dds/featu add_subdirectory(tools) add_subdirectory(ddsrt) -if(NOT CMAKE_CROSSCOMPILING AND BUILD_IDLC) +if(BUILD_IDLC) add_subdirectory(idl) endif() add_subdirectory(security) diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index f9fa37dc02..bc1f57a6bd 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -11,10 +11,11 @@ # set(defconfig_src "${CMAKE_CURRENT_BINARY_DIR}/defconfig.c") + add_custom_command( OUTPUT ${defconfig_src} - COMMAND ddsconf -f defconfig -o ${defconfig_src} - DEPENDS ddsconf) + COMMAND ddsconf-native -f defconfig -o ${defconfig_src} + DEPENDS ddsconf-native) set(srcs_ddsi ddsi_eth.c diff --git a/src/core/xtests/cdrtest/CMakeLists.txt b/src/core/xtests/cdrtest/CMakeLists.txt index 40678a5311..0aeb1ad731 100644 --- a/src/core/xtests/cdrtest/CMakeLists.txt +++ b/src/core/xtests/cdrtest/CMakeLists.txt @@ -11,7 +11,7 @@ # cmake_minimum_required(VERSION 3.5) -find_package(CycloneDDS COMPONENTS idlc) +find_package(CycloneDDS REQUIRED) add_compile_options("-I${PROJECT_SOURCE_DIR}/src/ddsrt/include") add_compile_options("-I${PROJECT_SOURCE_DIR}/src/core/ddsc/include") diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 72fdcfeeec..32591fe9e3 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -12,8 +12,6 @@ set(CMAKE_INSTALL_TOOLSDIR "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/tools") add_subdirectory(pubsub) add_subdirectory(ddsconf) -if(BUILD_IDLC) - add_subdirectory(idlpp) - add_subdirectory(idlc) - add_subdirectory(ddsperf) -endif() +add_subdirectory(idlpp) +add_subdirectory(idlc) +add_subdirectory(ddsperf) diff --git a/src/tools/ddsconf/CMakeLists.txt b/src/tools/ddsconf/CMakeLists.txt index b11783a1a5..d3ba4275a6 100644 --- a/src/tools/ddsconf/CMakeLists.txt +++ b/src/tools/ddsconf/CMakeLists.txt @@ -9,14 +9,8 @@ # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # -if(CMAKE_CROSSCOMPILING) - find_program(DDSCONF_EXECUTABLE ddsconf REQUIRED) - if(NOT DDSCONF_EXECUTABLE) - message(FATAL_ERROR "ddsconf not found!") - endif() - add_executable(ddsconf IMPORTED GLOBAL) - set_property(TARGET ddsconf PROPERTY IMPORTED_LOCATION ${DDSCONF_EXECUTABLE}) -else() + +if (BUILD_DDSCONF) include(GenerateDummyExportHeader) add_executable(ddsconf @@ -37,4 +31,42 @@ else() "${CMAKE_CURRENT_BINARY_DIR}/include" $> $) + + add_executable(${PROJECT_NAME}::ddsconf ALIAS ddsconf) + + install( + TARGETS ddsconf + EXPORT "${CMAKE_PROJECT_NAME}" + DESTINATION "${CMAKE_INSTALL_BINDIR}" + COMPONENT dev) + + if (CMAKE_CROSSCOMPILING) + find_program(_executable ddsconf REQUIRED NO_CMAKE_FIND_ROOT_PATH) + + # REQUIRED is not working until cmake 3.18 so it might still not exist + if (NOT _executable) + message(FATAL_ERROR "Could not find a native ddsconf executable, please make sure it is available on PATH") + endif() + + add_executable(ddsconf-native IMPORTED GLOBAL) + set_property(TARGET ddsconf-native PROPERTY IMPORTED_LOCATION "${_executable}") + message(STATUS "Using imported native ddsconf ${_executable}") + else() + add_executable(ddsconf-native ALIAS ddsconf) + endif() +else() + # Note, no if crosscompiling statement here, ddsconf is _required_ + # so if you don't BUILD_DDSCONF it has to be found + find_program(_executable ddsconf REQUIRED NO_CMAKE_FIND_ROOT_PATH) + + # REQUIRED is not working until cmake 3.18 so it might still not exist + if (NOT _executable) + message(FATAL_ERROR "Could not find a native ddsconf executable, please make sure it is available on PATH") + endif() + + add_executable(ddsconf-native IMPORTED GLOBAL) + set_property(TARGET ddsconf-native PROPERTY IMPORTED_LOCATION "${_executable}") + message(STATUS "Using imported native ddsconf ${_executable}") endif() + + diff --git a/src/tools/ddsperf/CMakeLists.txt b/src/tools/ddsperf/CMakeLists.txt index ddf87b2332..aba9221e3f 100644 --- a/src/tools/ddsperf/CMakeLists.txt +++ b/src/tools/ddsperf/CMakeLists.txt @@ -10,6 +10,8 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # +include(Generate) + idlc_generate(TARGET ddsperf_types FILES ddsperf_types.idl) add_executable(ddsperf ddsperf.c cputime.c cputime.h netload.c netload.h) target_link_libraries(ddsperf ddsperf_types ddsc) @@ -29,4 +31,4 @@ if (MSVC) COMPONENT dev OPTIONAL ) -endif() +endif() \ No newline at end of file diff --git a/src/tools/idlc/CMakeLists.txt b/src/tools/idlc/CMakeLists.txt index 86cc5b88ab..cf2714547c 100644 --- a/src/tools/idlc/CMakeLists.txt +++ b/src/tools/idlc/CMakeLists.txt @@ -9,87 +9,88 @@ # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # -if(CMAKE_CROSSCOMPILING) - find_program(IDLC_EXECUTABLE idlc REQUIRED) - add_executable(CycloneDDS::idlc IMPORTED GLOBAL) - set_property(TARGET CycloneDDS::idlc PROPERTY IMPORTED_LOCATION ${IDLC_EXECUTABLE}) -else() - include(CheckIncludeFile) - check_include_file(getopt.h HAVE_GETOPT_H) +if (NOT BUILD_IDLC) + return() +endif() - configure_file(src/config.h.in config.h) +include(CheckIncludeFile) - set(headers - src/descriptor.h - src/generator.h - src/options.h - src/plugin.h - include/idlc/generator.h - ${CMAKE_CURRENT_BINARY_DIR}/config.h) - set(sources - src/idlc.c - src/plugin.c - src/options.c - src/generator.c - src/descriptor.c - src/types.c) - add_executable(idlc ${sources} ${headers}) +check_include_file(getopt.h HAVE_GETOPT_H) - if(MSVC) - # ignore warnings C6255 and 6263 about _alloca - target_compile_options(idlc PRIVATE /wd6255 /wd6263) - endif() - target_link_libraries(idlc PRIVATE idl idlpp ${CMAKE_DL_LIBS}) - target_include_directories( - idlc PRIVATE - include - ${CMAKE_CURRENT_BINARY_DIR} - $>) +configure_file(src/config.h.in config.h) - if(WIN32 OR NOT HAVE_GETOPT_H) - # use getopt.h from ddsrt - file(READ "${CMAKE_SOURCE_DIR}/src/ddsrt/include/getopt.h.in" getopt_h) - # remove occurrences of DDS_EXPORT - string(REGEX REPLACE "\n[ \t]*DDS_EXPORT[ \t]+" "\n" getopt_h "${getopt_h}") - # remove dds/* includes - string(REGEX REPLACE "\n[ \t]*#[ \t]*include[ \t]+[<\"]dds/[^\n]*" "" getopt_h "${getopt_h}") - # generate getopt.h - file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/getopt.h" CONTENT "${getopt_h}") - target_include_directories(idlc PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") - # add getopt.c - configure_file( - "${CMAKE_SOURCE_DIR}/src/ddsrt/src/getopt.c" - "${CMAKE_CURRENT_BINARY_DIR}/getopt.c" - COPYONLY) - target_sources(idlc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/getopt.c) - endif() +set(headers + src/descriptor.h + src/generator.h + src/options.h + src/plugin.h + include/idlc/generator.h + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +set(sources + src/idlc.c + src/plugin.c + src/options.c + src/generator.c + src/descriptor.c + src/types.c) +add_executable(idlc ${sources} ${headers}) - add_executable(${PROJECT_NAME}::idlc ALIAS idlc) +if(MSVC) + # ignore warnings C6255 and 6263 about _alloca + target_compile_options(idlc PRIVATE /wd6255 /wd6263) +endif() +target_link_libraries(idlc PRIVATE idl idlpp ${CMAKE_DL_LIBS}) +target_include_directories( + idlc PRIVATE + include + ${CMAKE_CURRENT_BINARY_DIR} + $>) - install( - DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/idlc" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - COMPONENT dev - FILES_MATCHING PATTERN "*.h") +if(WIN32 OR NOT HAVE_GETOPT_H) + # use getopt.h from ddsrt + file(READ "${CMAKE_SOURCE_DIR}/src/ddsrt/include/getopt.h.in" getopt_h) + # remove occurrences of DDS_EXPORT + string(REGEX REPLACE "\n[ \t]*DDS_EXPORT[ \t]+" "\n" getopt_h "${getopt_h}") + # remove dds/* includes + string(REGEX REPLACE "\n[ \t]*#[ \t]*include[ \t]+[<\"]dds/[^\n]*" "" getopt_h "${getopt_h}") + # generate getopt.h + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/getopt.h" CONTENT "${getopt_h}") + target_include_directories(idlc PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + # add getopt.c + configure_file( + "${CMAKE_SOURCE_DIR}/src/ddsrt/src/getopt.c" + "${CMAKE_CURRENT_BINARY_DIR}/getopt.c" + COPYONLY) + target_sources(idlc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/getopt.c) +endif() - install( - TARGETS idlc - EXPORT "${CMAKE_PROJECT_NAME}" - DESTINATION "${CMAKE_INSTALL_BINDIR}" - COMPONENT dev) - if (MSVC) - install(FILES $ - DESTINATION "${CMAKE_INSTALL_BINDIR}" - COMPONENT dev - OPTIONAL - ) - endif() +add_executable(${PROJECT_NAME}::idlc ALIAS idlc) + +install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/idlc" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT dev + FILES_MATCHING PATTERN "*.h") - install( - FILES Generate.cmake - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/idlc" - COMPONENT dev) +install( + TARGETS idlc + EXPORT "${CMAKE_PROJECT_NAME}" + DESTINATION "${CMAKE_INSTALL_BINDIR}" + COMPONENT dev) + +if (MSVC) + install(FILES $ + DESTINATION "${CMAKE_INSTALL_BINDIR}" + COMPONENT dev + OPTIONAL + ) endif() -include(Generate.cmake) +install( + FILES "${CMAKE_SOURCE_DIR}/cmake/Modules/Generate.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/idlc" + COMPONENT dev) + +include("${CMAKE_SOURCE_DIR}/cmake/Modules/Generate.cmake") + diff --git a/src/tools/idlpp/CMakeLists.txt b/src/tools/idlpp/CMakeLists.txt index cca2b9ca98..368e262fb5 100644 --- a/src/tools/idlpp/CMakeLists.txt +++ b/src/tools/idlpp/CMakeLists.txt @@ -9,8 +9,8 @@ # # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # -if(CMAKE_CROSSCOMPILING) - # Do not build preprocessor if cross compiling + +if (NOT BUILD_IDLC) return() endif() diff --git a/src/tools/idlpp/src/configed.H.in b/src/tools/idlpp/src/configed.H.in index 16b084f021..b01284f1c8 100644 --- a/src/tools/idlpp/src/configed.H.in +++ b/src/tools/idlpp/src/configed.H.in @@ -38,7 +38,7 @@ compiled to language-specific sources, not machine code. */ /* Define the cpu-specific-macro. */ -#define CPU "" +#define CPU "undefined" /* Define the target system. */ #define SYSTEM @idlpp_system@ From f80279362f533f7b0b0bbe985a14ceab94bcaf14 Mon Sep 17 00:00:00 2001 From: Thijs Miedema Date: Thu, 30 Sep 2021 21:36:38 +0200 Subject: [PATCH 21/37] Fix incorrect bitshift in filetime_to_time. --- src/ddsrt/src/rusage/windows/rusage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ddsrt/src/rusage/windows/rusage.c b/src/ddsrt/src/rusage/windows/rusage.c index cafec5a936..f8e232e9e2 100644 --- a/src/ddsrt/src/rusage/windows/rusage.c +++ b/src/ddsrt/src/rusage/windows/rusage.c @@ -21,7 +21,7 @@ static dds_time_t filetime_to_time (const FILETIME *ft) { /* FILETIME structures express times in 100-nanosecond time units. */ - return (dds_time_t) ((((uint64_t) ft->dwHighDateTime << 31) + (ft->dwLowDateTime)) * 100); + return (dds_time_t) ((((uint64_t) ft->dwHighDateTime << 32) + (ft->dwLowDateTime)) * 100); } dds_return_t From 61348b090ee75c64cc3aef73dbca7a78b33c9c88 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 22 Sep 2021 09:37:32 +0200 Subject: [PATCH 22/37] Add coverity modelling file Signed-off-by: Erik Boasson --- etc/coverity-model.c | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 etc/coverity-model.c diff --git a/etc/coverity-model.c b/etc/coverity-model.c new file mode 100644 index 0000000000..66e21e424c --- /dev/null +++ b/etc/coverity-model.c @@ -0,0 +1,7 @@ +int CU_assertImplementation (int bValue, unsigned uiLine, const char *strCondition, const char *strFile, const char *strFunction, int bFatal) +{ + if (!bValue && bFatal) { + __coverity_panic__ (); + } + return bValue; +} From 2ec1ed6720f5e504af4f6872a69c21cef337d23e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 22 Sep 2021 17:36:51 +0200 Subject: [PATCH 23/37] Propagate envvar expansion error in config Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index e83b197df2..2ca7c84fe6 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -1962,6 +1962,8 @@ static int proc_update_cfgelem (struct cfgst *cfgst, const struct cfgelem *ce, c { void *parent = cfgst_parent (cfgst); char *xvalue = ddsrt_expand_envvars (value, cfgst->cfg->domainId); + if (xvalue == NULL) + return -1; enum update_result res; cfgst_push (cfgst, isattr, isattr ? ce : NULL, parent); res = do_update (cfgst, ce->update, parent, ce, xvalue, cfgst->source); From bee385a1e305ac725abf5528ef737bbb98bbebc1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 22 Sep 2021 18:14:38 +0200 Subject: [PATCH 24/37] Handle too deeply nested XML configs There is a maximum nesting depth for the configuration that is determined by the internal configuration tables. Simply aborting the interpretation of the XML input on the first unrecognized element item would guarantee never exceeding the maximum nesting depth. As an error handling strategy this is less user-friendly than ignoring some of the input, attempting to interpret the remainder and reporting any further issues. This commit makes it abort the interpretation as soon as the maximum nesting depth is reached, in all other cases it continues and reports as many issues with the configuration as it can. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 88 +++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 2ca7c84fe6..56d859dbb7 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -355,15 +355,43 @@ static const struct unit unittab_bandwidth_Bps[] = { static void free_configured_elements (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem); static void free_configured_element (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem); static const struct cfgelem *lookup_element (const char *target, bool *isattr); +static enum update_result cfg_error (struct cfgst *cfgst, const char *fmt, ...) ddsrt_attribute_format_printf(2, 3); -static void cfgst_push (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) +static bool cfgst_push_maybe_reservespace (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent, bool allow_reservespace) { - assert(cfgst->path_depth < MAX_PATH_DEPTH); assert(isattr == 0 || isattr == 1); + if (cfgst->path_depth >= MAX_PATH_DEPTH - (allow_reservespace ? 0 : 1)) + { + cfg_error (cfgst, "XML too deeply nested"); + return false; + } cfgst->isattr[cfgst->path_depth] = isattr; cfgst->path[cfgst->path_depth] = elem; cfgst->parent[cfgst->path_depth] = parent; cfgst->path_depth++; + return true; +} + +static bool cfgst_push (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) + ddsrt_attribute_warn_unused_result; + +static bool cfgst_push (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) +{ + return cfgst_push_maybe_reservespace (cfgst, isattr, elem, parent, false); +} + +static void cfgst_push_nofail (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) +{ + bool ok = cfgst_push_maybe_reservespace (cfgst, isattr, elem, parent, false); + assert (ok); + (void) ok; +} + +static void cfgst_push_errorhandling (struct cfgst *cfgst, int isattr, const struct cfgelem *elem, void *parent) +{ + bool ok = cfgst_push_maybe_reservespace (cfgst, isattr, elem, parent, true); + assert (ok); + (void) ok; } static void cfgst_pop (struct cfgst *cfgst) @@ -542,8 +570,6 @@ static void cfg_warning (struct cfgst *cfgst, const char *fmt, ...) } while (bsz > 0); } -static enum update_result cfg_error (struct cfgst *cfgst, const char *fmt, ...) ddsrt_attribute_format_printf(2, 3); - static enum update_result cfg_error (struct cfgst *cfgst, const char *fmt, ...) { va_list ap; @@ -1577,7 +1603,8 @@ static int set_defaults (struct cfgst *cfgst, void *parent, int isattr, struct c struct cfgst_nodekey key; key.e = ce; key.p = parent; - cfgst_push (cfgst, isattr, ce, parent); + // running over internal tables, so stack must be large enough + cfgst_push_nofail (cfgst, isattr, ce, parent); if (ce->multiplicity <= 1) { if (ddsrt_avl_lookup (&cfgst_found_treedef, &cfgst->found, &key) == NULL) @@ -1585,7 +1612,7 @@ static int set_defaults (struct cfgst *cfgst, void *parent, int isattr, struct c if (ce->update) { int ok1; - cfgst_push (cfgst, 0, NULL, NULL); + cfgst_push_nofail (cfgst, 0, NULL, NULL); ok1 = set_default (cfgst, parent, ce); cfgst_pop (cfgst); ok = ok && ok1; @@ -1611,13 +1638,14 @@ static void print_configitems (struct cfgst *cfgst, void *parent, int isattr, st continue; key.e = ce; key.p = parent; - cfgst_push (cfgst, isattr, ce, parent); + // running over internal tables, so stack must be large enough + cfgst_push_nofail (cfgst, isattr, ce, parent); if ((n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL) sources = n->sources; if (ce->multiplicity <= 1) { - cfgst_push (cfgst, 0, NULL, NULL); + cfgst_push_nofail (cfgst, 0, NULL, NULL); if (ce->print) ce->print (cfgst, parent, ce, sources); cfgst_pop (cfgst); @@ -1631,7 +1659,7 @@ static void print_configitems (struct cfgst *cfgst, void *parent, int isattr, st struct ddsi_config_listelem *p = cfg_deref_address (cfgst, parent, ce); while (p) { - cfgst_push (cfgst, 0, NULL, NULL); + cfgst_push_nofail (cfgst, 0, NULL, NULL); if (ce->print) ce->print (cfgst, p, ce, sources); cfgst_pop(cfgst); @@ -1872,7 +1900,7 @@ static const struct cfgelem *find_cfgelem_by_name (struct cfgst * const cfgst, c struct cfgelem const * const cfg_subelem_orig = cfg_subelem; bool isattr; cfg_subelem = lookup_element (cfg_subelem->defvalue, &isattr); - cfgst_push (cfgst, 0, cfg_subelem_orig, NULL); + cfgst_push_errorhandling (cfgst, 0, cfg_subelem_orig, NULL); cfg_warning (cfgst, "setting%s moved to //%s", cfg_subelem->children ? "s" : "", cfg_subelem_orig->defvalue); cfgst_pop (cfgst); } @@ -1890,13 +1918,14 @@ static int proc_elem_open (void *varg, UNUSED_ARG (uintptr_t parentinfo), UNUSED cfgst->implicit_toplevel = ITL_DISALLOWED; else { - cfgst_push (cfgst, 0, &cyclonedds_root_cfgelems[0], cfgst_parent (cfgst)); + /* If pushing CycloneDDS and/or Domain is impossible, the stack depth is simply to small */ + cfgst_push_nofail (cfgst, 0, &cyclonedds_root_cfgelems[0], cfgst_parent (cfgst)); /* Most likely one would want to override some domain settings without bothering, so also allow an implicit "Domain" */ cfgst->implicit_toplevel = ITL_INSERTED_1; if (ddsrt_strcasecmp (name, "Domain") != 0) { - cfgst_push (cfgst, 0, &root_cfgelems[0], cfgst_parent (cfgst)); + cfgst_push_nofail (cfgst, 0, &root_cfgelems[0], cfgst_parent (cfgst)); cfgst->implicit_toplevel = ITL_INSERTED_2; } cfgst->source = (cfgst->source == 0) ? 1 : cfgst->source << 1; @@ -1907,23 +1936,20 @@ static int proc_elem_open (void *varg, UNUSED_ARG (uintptr_t parentinfo), UNUSED const struct cfgelem *cfgelem = cfgst_tos (cfgst); if (cfgelem == NULL) { - /* Ignoring, but do track the structure so we can know when to stop ignoring */ - cfgst_push (cfgst, 0, NULL, NULL); - return 1; + /* Ignoring, but do track the structure so we can know when to stop ignoring, abort if it is nested too deeply */ + return cfgst_push (cfgst, 0, NULL, NULL) ? 1 : -1; } const struct cfgelem * const cfg_subelem = find_cfgelem_by_name (cfgst, "element", cfgelem->children, name); if (cfg_subelem == NULL) { /* Ignore the element, continue parsing */ - cfgst_push (cfgst, 0, NULL, NULL); - return 0; + return cfgst_push (cfgst, 0, NULL, NULL) ? 0 : -1; } if (strcmp (cfg_subelem->name, "*") == 0) { /* Push a marker that we are to ignore this part of the DOM tree */ - cfgst_push (cfgst, 0, NULL, NULL); - return 1; + return cfgst_push (cfgst, 0, NULL, NULL) ? 1 : -1; } else { @@ -1941,7 +1967,8 @@ static int proc_elem_open (void *varg, UNUSED_ARG (uintptr_t parentinfo), UNUSED else dynparent = cfg_deref_address (cfgst, parent, cfg_subelem); - cfgst_push (cfgst, 0, cfg_subelem, dynparent); + if (!cfgst_push (cfgst, 0, cfg_subelem, dynparent)) + return -1; if (cfg_subelem == &cyclonedds_root_cfgelems[0]) { @@ -1965,9 +1992,13 @@ static int proc_update_cfgelem (struct cfgst *cfgst, const struct cfgelem *ce, c if (xvalue == NULL) return -1; enum update_result res; - cfgst_push (cfgst, isattr, isattr ? ce : NULL, parent); - res = do_update (cfgst, ce->update, parent, ce, xvalue, cfgst->source); - cfgst_pop (cfgst); + if (!cfgst_push (cfgst, isattr, isattr ? ce : NULL, parent)) + res = URES_ERROR; + else + { + res = do_update (cfgst, ce->update, parent, ce, xvalue, cfgst->source); + cfgst_pop (cfgst); + } ddsrt_free (xvalue); /* Push a marker that we are to ignore this part of the DOM tree -- see the @@ -1985,16 +2016,18 @@ static int proc_update_cfgelem (struct cfgst *cfgst, const struct cfgelem *ce, c So replacing the top stack entry for an attribute and the top two entries if it's text is a reasonable interpretation of SKIP. And it seems quite - likely that it won't be used for anything else ... */ + likely that it won't be used for anything else ... + + After popping an element, pushing one must succeed. */ if (res == URES_SKIP_ELEMENT) { cfgst_pop (cfgst); if (!isattr) { cfgst_pop (cfgst); - cfgst_push (cfgst, 0, NULL, NULL); + cfgst_push_nofail (cfgst, 0, NULL, NULL); } - cfgst_push (cfgst, 0, NULL, NULL); + cfgst_push_nofail (cfgst, 0, NULL, NULL); } else { @@ -2286,7 +2319,8 @@ struct cfgst *config_init (const char *config, struct ddsi_config *cfg, uint32_t cfgst->implicit_toplevel = (fp == NULL) ? ITL_ALLOWED : ITL_DISALLOWED; cfgst->partial_match_allowed = (fp == NULL); cfgst->first_data_in_source = true; - cfgst_push (cfgst, 0, &root_cfgelem, cfgst->cfg); + // top-level entry must fit + cfgst_push_nofail (cfgst, 0, &root_cfgelem, cfgst->cfg); ok = (ddsrt_xmlp_parse (qx) >= 0) && !cfgst->error; assert (!ok || (cfgst->path_depth == 1 && cfgst->implicit_toplevel == ITL_DISALLOWED) || From a35ce4d9c29d16644a14fae04bd524074d43fe63 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 23 Sep 2021 15:27:45 +0200 Subject: [PATCH 25/37] Test handling invalid envvar expansion in config Signed-off-by: Erik Boasson --- src/core/ddsc/tests/config.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/core/ddsc/tests/config.c b/src/core/ddsc/tests/config.c index e2376ae81e..d0cea9d58b 100644 --- a/src/core/ddsc/tests/config.c +++ b/src/core/ddsc/tests/config.c @@ -353,3 +353,36 @@ CU_Test(ddsc_security_qos, empty, .init = ddsrt_init, .fini = ddsrt_fini) CU_ASSERT_FATAL (found == 0x3); #endif } + +CU_Test(ddsc_config, invalid_envvar, .init = ddsrt_init, .fini = ddsrt_fini) +{ + const char *log_expected[] = { + "*invalid expansion*", + NULL + }; + + dds_set_log_mask (DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); + dds_set_log_sink (&logger, (void *) log_expected); + dds_set_trace_sink (&logger, (void *) log_expected); + + found = 0; + dds_entity_t domain; + domain = dds_create_domain (0, "${INVALID_EXPANSION"); + CU_ASSERT_FATAL (domain < 0); + CU_ASSERT_FATAL (found == 0x1); + + found = 0; + domain = dds_create_domain (0, ""); + CU_ASSERT_FATAL (domain < 0); + CU_ASSERT_FATAL (found == 0x1); + + dds_set_log_sink (NULL, NULL); + dds_set_trace_sink (NULL, NULL); +} + +CU_Test(ddsc_config, too_deep_nesting, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain; + domain = dds_create_domain (0, ""); + CU_ASSERT_FATAL (domain < 0); +} From c8d4ab41cac0eba047870217e57cf3b95506322f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 23 Sep 2021 15:41:17 +0200 Subject: [PATCH 26/37] Test too deeply nested XML in configurations Signed-off-by: Erik Boasson --- src/core/ddsc/tests/config.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/core/ddsc/tests/config.c b/src/core/ddsc/tests/config.c index d0cea9d58b..4353ef7837 100644 --- a/src/core/ddsc/tests/config.c +++ b/src/core/ddsc/tests/config.c @@ -382,7 +382,20 @@ CU_Test(ddsc_config, invalid_envvar, .init = ddsrt_init, .fini = ddsrt_fini) CU_Test(ddsc_config, too_deep_nesting, .init = ddsrt_init, .fini = ddsrt_fini) { - dds_entity_t domain; - domain = dds_create_domain (0, ""); + const char *log_expected[] = { + "*too deeply nested*", + NULL + }; + + dds_set_log_mask (DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); + dds_set_log_sink (&logger, (void *) log_expected); + dds_set_trace_sink (&logger, (void *) log_expected); + + found = 0; + dds_entity_t domain = dds_create_domain (0, ""); CU_ASSERT_FATAL (domain < 0); + CU_ASSERT_FATAL (found == 0x1); + + dds_set_log_sink (NULL, NULL); + dds_set_trace_sink (NULL, NULL); } From 7baf8cc10c81ab23084f1fa27af001afd5984886 Mon Sep 17 00:00:00 2001 From: Martijn Reicher Date: Wed, 29 Sep 2021 15:58:55 +0200 Subject: [PATCH 27/37] Fix for issue #968 - This fixes #968 - Add a byte swap to the participant GUID prefix Signed-off-by: Martijn Reicher --- src/core/ddsi/src/q_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index af493c66ee..252bea686e 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1552,6 +1552,7 @@ int rtps_init (struct ddsi_domaingv *gv) gv->ppguid_base.prefix.s[1] = NN_VENDORID_ECLIPSE.id[1]; DDSRT_STATIC_ASSERT (sizeof (gv->ppguid_base.prefix.s) > 2 && sizeof (gv->ppguid_base.prefix.s) - 2 <= sizeof (digest)); memcpy (&gv->ppguid_base.prefix.s[2], digest, sizeof (gv->ppguid_base.prefix.s) - 2); + gv->ppguid_base.prefix = nn_ntoh_guid_prefix (gv->ppguid_base.prefix); gv->ppguid_base.entityid.u = NN_ENTITYID_PARTICIPANT; } From 4bab618a74949638393cf17a7b10e1f439520bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20Lind=C3=A9n?= <_@robinlinden.eu> Date: Mon, 4 Oct 2021 13:58:46 +0200 Subject: [PATCH 28/37] Fix use of non-existent paths when building as a subproject MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CMAKE_SOURCE_DIR always points to the top-level CMake project, so if CycloneDDS was included as a gitmodule or pulled in using CMake FetchContent, the CMake step would fail with errors like ``` CMake Error at cyclonedds/src/tools/idlc/CMakeLists.txt:52 (file): file failed to open for reading (No such file or directory): /home/robin/dds-project/src/ddsrt/include/getopt.h.in CMake Error: File /home/robin/dds-project/src/ddsrt/src/getopt.c does not exist. CMake Error at cyclonedds/src/tools/idlc/CMakeLists.txt:61 (configure_file): configure_file Problem configuring file CMake Error at cyclonedds/src/tools/idlc/CMakeLists.txt:95 (include): include could not find load file: /home/robin/dds-project/cmake/Modules/Generate.cmake ``` This commit replaces CMAKE_SOURCE_DIR with _SOURCE_DIR, a variable that always points to the source dir of the named project. See: https://cmake.org/cmake/help/v3.21/variable/CMAKE_SOURCE_DIR.html https://cmake.org/cmake/help/v3.21/variable/PROJECT-NAME_SOURCE_DIR.html Signed-off-by: Robin Lindén <_@robinlinden.eu> --- examples/CMakeLists.txt | 2 +- src/tools/idlc/CMakeLists.txt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 2e50f3ebb4..df7ef2061e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -11,7 +11,7 @@ # set(CMAKE_INSTALL_EXAMPLESDIR "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/examples") -include("${CMAKE_SOURCE_DIR}/cmake/Modules/Generate.cmake") +include("${CycloneDDS_SOURCE_DIR}/cmake/Modules/Generate.cmake") install( FILES diff --git a/src/tools/idlc/CMakeLists.txt b/src/tools/idlc/CMakeLists.txt index cf2714547c..1066adc70d 100644 --- a/src/tools/idlc/CMakeLists.txt +++ b/src/tools/idlc/CMakeLists.txt @@ -49,7 +49,7 @@ target_include_directories( if(WIN32 OR NOT HAVE_GETOPT_H) # use getopt.h from ddsrt - file(READ "${CMAKE_SOURCE_DIR}/src/ddsrt/include/getopt.h.in" getopt_h) + file(READ "${CycloneDDS_SOURCE_DIR}/src/ddsrt/include/getopt.h.in" getopt_h) # remove occurrences of DDS_EXPORT string(REGEX REPLACE "\n[ \t]*DDS_EXPORT[ \t]+" "\n" getopt_h "${getopt_h}") # remove dds/* includes @@ -59,7 +59,7 @@ if(WIN32 OR NOT HAVE_GETOPT_H) target_include_directories(idlc PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") # add getopt.c configure_file( - "${CMAKE_SOURCE_DIR}/src/ddsrt/src/getopt.c" + "${CycloneDDS_SOURCE_DIR}/src/ddsrt/src/getopt.c" "${CMAKE_CURRENT_BINARY_DIR}/getopt.c" COPYONLY) target_sources(idlc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/getopt.c) @@ -88,9 +88,9 @@ if (MSVC) endif() install( - FILES "${CMAKE_SOURCE_DIR}/cmake/Modules/Generate.cmake" + FILES "${CycloneDDS_SOURCE_DIR}/cmake/Modules/Generate.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/idlc" COMPONENT dev) -include("${CMAKE_SOURCE_DIR}/cmake/Modules/Generate.cmake") +include("${CycloneDDS_SOURCE_DIR}/cmake/Modules/Generate.cmake") From 01319402508f6dfecb340f37f602f975dcea8306 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 13 Oct 2021 13:11:39 +0200 Subject: [PATCH 29/37] Bump version number to 0.8.1 Signed-off-by: Erik Boasson --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d04f699ef..0e029b8a97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # cmake_minimum_required(VERSION 3.7) -project(CycloneDDS VERSION 0.8.0 LANGUAGES C) +project(CycloneDDS VERSION 0.8.1 LANGUAGES C) if(CMAKE_VERSION VERSION_LESS 3.12) # GENERATE_EXPORT_HEADER requires a C++ compiler up to version 3.12 enable_language(CXX) From c59f75222d1336e9895a6e205663809c73e8e17c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 13 Oct 2021 13:11:22 +0200 Subject: [PATCH 30/37] Rename libidl to libcycloneddsidl Signed-off-by: Erik Boasson --- src/idl/CMakeLists.txt | 1 + src/tools/idlc/src/plugin.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/idl/CMakeLists.txt b/src/idl/CMakeLists.txt index c4e9bb8fc5..7e322c0a0d 100644 --- a/src/idl/CMakeLists.txt +++ b/src/idl/CMakeLists.txt @@ -82,6 +82,7 @@ add_library( set_target_properties( idl PROPERTIES + OUTPUT_NAME "cycloneddsidl" VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) diff --git a/src/tools/idlc/src/plugin.c b/src/tools/idlc/src/plugin.c index 4a16428180..fa1c5ac62f 100644 --- a/src/tools/idlc/src/plugin.c +++ b/src/tools/idlc/src/plugin.c @@ -19,14 +19,14 @@ #if WIN32 #include static const char sep[] = "/\\"; -static const char lib[] = ""; +static const char lib[] = "cyclonedds"; static const char ext[] = "dll"; #define SUBPROCESS_POPEN _popen #define SUBPROCESS_PCLOSE _pclose #else #include static const char sep[] = "/"; -static const char lib[] = "lib"; +static const char lib[] = "libcyclonedds"; #if __APPLE__ static const char ext[] = "dylib"; #else From 876f1490665e5fda59c7a52af237f03dbb8b1200 Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Fri, 19 Nov 2021 20:32:07 +0000 Subject: [PATCH 31/37] Fix warning when building CycloneDDS with gcc 11. gcc 11 warns that there is a conversion from 'long int' to 'uint32_t' when assigning the value of PTHREAD_STACK_MIN to tattr.stackSize. It's pedantically correct; tattr.stackSize is a uint32_t, and PTHREAD_STACK_MIN is either an integer (if it is hard-coded), or the result of calling sysconf(), which always returns a long. In either case it is a signed value, so we should explicitly cast it to uint32_t here. This quiets the warning. Signed-off-by: Chris Lalancette --- src/ddsrt/src/threads/posix/threads.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ddsrt/src/threads/posix/threads.c b/src/ddsrt/src/threads/posix/threads.c index 5feaad2a97..50e939fafc 100644 --- a/src/ddsrt/src/threads/posix/threads.c +++ b/src/ddsrt/src/threads/posix/threads.c @@ -237,8 +237,8 @@ ddsrt_thread_create ( if (tattr.stackSize != 0) { #ifdef PTHREAD_STACK_MIN - if (tattr.stackSize < PTHREAD_STACK_MIN) - tattr.stackSize = PTHREAD_STACK_MIN; + if (tattr.stackSize < (uint32_t)PTHREAD_STACK_MIN) + tattr.stackSize = (uint32_t)PTHREAD_STACK_MIN; #endif if ((result = pthread_attr_setstacksize (&attr, tattr.stackSize)) != 0) { From 8e7fd85df9042f5ef217e6852f471150442804fc Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 21 Dec 2021 14:48:06 +0100 Subject: [PATCH 32/37] Detect overflow in idlc when stashing instructions This makes idlc show an error message in case the maximum number of instructions is reached. Because of 16-bits offset fields in the instructions, the maximum number of instructions that can be used is limited to 65k. Signed-off-by: Dennis Potman --- src/tools/idlc/src/descriptor.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/tools/idlc/src/descriptor.c b/src/tools/idlc/src/descriptor.c index 50dd55bf0a..61791c73ae 100644 --- a/src/tools/idlc/src/descriptor.c +++ b/src/tools/idlc/src/descriptor.c @@ -30,8 +30,10 @@ #define SUBTYPE (8) #define MAX_SIZE (16) +#define INST_SLOT_SZ (100) +#define MAX_INST ((UINT16_MAX / INST_SLOT_SZ) * INST_SLOT_SZ) -static const uint16_t nop = UINT16_MAX; +static const uint16_t nop = MAX_INST; /* store each instruction separately for easy post processing and reduced complexity. arrays and sequences introduce a new scope and the relative @@ -204,7 +206,12 @@ stash_instruction( { /* make more slots available as necessary */ if (descriptor->instructions.count == descriptor->instructions.size) { - uint32_t size = descriptor->instructions.size + 100; + if (descriptor->instructions.size + INST_SLOT_SZ > MAX_INST) + { + idl_error (NULL, NULL, "Maximum number of instructions (%"PRIu16") reached", MAX_INST); + return IDL_RETCODE_NO_SPACE; + } + uint32_t size = descriptor->instructions.size + INST_SLOT_SZ; struct instruction *table = descriptor->instructions.table; if (!(table = realloc(table, size * sizeof(*table)))) return IDL_RETCODE_NO_MEMORY; @@ -1410,7 +1417,15 @@ generate_descriptor( if ((ret = push_type(&descriptor, node, NULL))) goto err_emit; if ((ret = idl_visit(pstate, ((const idl_struct_t *)node)->members, &visitor, &descriptor))) + { + while (descriptor.types) + { + while (descriptor.types->fields && (!descriptor.types->previous || descriptor.types->fields != descriptor.types->previous->fields)) + pop_field (&descriptor); + pop_type (&descriptor); + } goto err_emit; + } pop_type(&descriptor); if ((ret = stash_opcode(&descriptor, nop, DDS_OP_RTS, 0u))) goto err_emit; From af7de8448a454288fb24c3cfd8822300989efa92 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 5 Jan 2022 09:24:03 +0100 Subject: [PATCH 33/37] Check package.xml and CMakeLists.txt are the same Signed-off-by: Erik Boasson --- .azure/templates/build-test.yml | 2 ++ versioncheck.bash | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 versioncheck.bash diff --git a/.azure/templates/build-test.yml b/.azure/templates/build-test.yml index 065eabc0b9..4fb6df11dd 100644 --- a/.azure/templates/build-test.yml +++ b/.azure/templates/build-test.yml @@ -15,6 +15,8 @@ # steps: + - bash: bash versioncheck.bash + name: versioncheck - task: UsePythonVersion@0 inputs: versionSpec: '3.8' diff --git a/versioncheck.bash b/versioncheck.bash new file mode 100644 index 0000000000..af131d7853 --- /dev/null +++ b/versioncheck.bash @@ -0,0 +1,12 @@ +read pv < <(tr '\t' ' ' < package.xml | sed -ne 's;^ * *\([0-9.][0-9.]*\) *;\1;p') +read cv < <(tr '\t' ' ' < CMakeLists.txt | sed -ne 's;^ *project *( *CycloneDDS .*VERSION *\([0-9.][0-9.]*\)[ )].*;\1;p') +echo "package.xml version: $pv" +echo "CMakeLists.txt version: $cv" +if [[ -z "$pv" || -z "$cv" ]] ; then + echo "version extraction failed" + exit 1 +fi +if [[ "$pv" != "$cv" ]] ; then + echo "version mismatch" + exit 1 +fi From d63de72fab679b028725bbe1c314767e689723a0 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 6 Jan 2022 16:12:07 +0100 Subject: [PATCH 34/37] Bump version to 0.8.2 Signed-off-by: Erik Boasson --- CMakeLists.txt | 2 +- package.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e029b8a97..7297ddb8a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # cmake_minimum_required(VERSION 3.7) -project(CycloneDDS VERSION 0.8.1 LANGUAGES C) +project(CycloneDDS VERSION 0.8.2 LANGUAGES C) if(CMAKE_VERSION VERSION_LESS 3.12) # GENERATE_EXPORT_HEADER requires a C++ compiler up to version 3.12 enable_language(CXX) diff --git a/package.xml b/package.xml index b1f3ecb703..74ecba9038 100644 --- a/package.xml +++ b/package.xml @@ -2,7 +2,7 @@ cyclonedds - 0.8.0 + 0.8.2 Eclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project. Eclipse Foundation, Inc. Eclipse Public License 2.0 From 93fdedcf0c99988147b04c22e13cb24dd2e8f74f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 1 Feb 2022 13:46:03 +0100 Subject: [PATCH 35/37] Set OpenSSL API compatibility to 1.1.1 This suppresses deprecation warnings from OpenSSL 3.0. It is not a proper fix, but the OpenSSL documentation on how to deal with the deprecations is such that it will take some time to fix this. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_ssl.c | 2 ++ src/security/openssl/include/dds/security/openssl_support.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/core/ddsi/src/ddsi_ssl.c b/src/core/ddsi/src/ddsi_ssl.c index d4f5460911..872a1ca19a 100644 --- a/src/core/ddsi/src/ddsi_ssl.c +++ b/src/core/ddsi/src/ddsi_ssl.c @@ -357,7 +357,9 @@ static SSL *ddsi_ssl_accept (const struct ddsi_domaingv *gv, BIO *bio, ddsrt_soc static bool ddsi_ssl_init (struct ddsi_domaingv *gv) { /* FIXME: allocate this stuff ... don't copy gv into a global variable ... */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_BIO_strings (); +#endif SSL_load_error_strings (); SSL_library_init (); OpenSSL_add_all_algorithms (); diff --git a/src/security/openssl/include/dds/security/openssl_support.h b/src/security/openssl/include/dds/security/openssl_support.h index 059edc7f0a..d330c2d02d 100644 --- a/src/security/openssl/include/dds/security/openssl_support.h +++ b/src/security/openssl/include/dds/security/openssl_support.h @@ -40,6 +40,8 @@ #include #endif +#define OPENSSL_API_COMPAT 10101 + #include #include #include From 57efec8d139e079fb68b058279302b1520501f9a Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Sun, 25 Apr 2021 13:58:02 -0400 Subject: [PATCH 36/37] Add read/write instrumentation with LTTng Signed-off-by: Christophe Bedard --- src/CMakeLists.txt | 14 ++++ src/core/ddsc/CMakeLists.txt | 11 ++- src/core/ddsc/src/dds_read.c | 2 + src/core/ddsc/src/dds_reader.c | 7 ++ src/core/ddsc/src/dds_write.c | 3 + src/core/ddsc/src/dds_writer.c | 7 ++ src/core/ddsc/src/tracing_lttng.c | 16 ++++ src/core/ddsc/src/tracing_lttng.h | 117 ++++++++++++++++++++++++++++++ src/features.h.in | 3 + 9 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 src/core/ddsc/src/tracing_lttng.c create mode 100644 src/core/ddsc/src/tracing_lttng.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e8ba113eaf..0527143d40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -111,6 +111,20 @@ if(NOT ENABLE_SECURITY) message(STATUS "Building without OMG DDS Security support") endif() +option(CYCLONE_ENABLE_TRACING "Enable building with static tracepoints with LTTng." OFF) +if(CYCLONE_ENABLE_TRACING AND CMAKE_SYSTEM_NAME MATCHES Linux) + find_package(PkgConfig) + if(PkgConfig_FOUND) + pkg_check_modules(LTTNG lttng-ust) + if(LTTNG_FOUND) + message(STATUS "Building with LTTng instrumentation support") + set(DDS_HAS_LTTNG_TRACING "1") + else() + message(FATAL_ERROR "CYCLONE_ENABLE_TRACING requires lttng-ust") + endif() + endif() +endif() + configure_file(features.h.in "${CMAKE_CURRENT_BINARY_DIR}/core/include/dds/features.h") add_subdirectory(tools) diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index cb6ef0b2d9..dd2318cc64 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -47,6 +47,10 @@ if (DDS_HAS_SHM) list(APPEND srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src/shm_monitor.c") endif() +if (DDS_HAS_LTTNG_TRACING) + list(APPEND srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src/tracing_lttng.c") +endif() + prepend(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src/" dds__alloc.h dds__builtin.h @@ -73,7 +77,8 @@ prepend(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src/" dds__whc_builtintopic.h dds__serdata_builtintopic.h dds__get_status.h - dds__data_allocator.h) + dds__data_allocator.h + tracing_lttng.h) prepend(hdrs_public_ddsc "$$/dds/" dds.h @@ -115,6 +120,10 @@ target_include_directories(ddsc INTERFACE $) +if (DDS_HAS_LTTNG_TRACING) + target_link_libraries(ddsc PRIVATE ${LTTNG_LIBRARIES} "-rdynamic") +endif() + install( DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/" diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index a2cd0fbf70..c7e30f6601 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -21,6 +21,7 @@ #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_sertype.h" #include "dds/ddsi/ddsi_sertopic.h" // for extern ddsi_sertopic_serdata_ops_wrap +#include "tracing_lttng.h" /* dds_read_impl: Core read/take function. Usually maxs is size of buf and si @@ -127,6 +128,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, } dds_entity_unpin (entity); thread_state_asleep (ts1); + TRACEPOINT(read, (const void *)rd, (const void *)*buf); return ret; #undef NC_CLEAR_LOAN_OUT diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 6f265cbb04..1ba29dc25a 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -35,6 +35,7 @@ #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/ddsi_security_omg.h" #include "dds/ddsi/ddsi_statistics.h" +#include "tracing_lttng.h" #ifdef DDS_HAS_SHM #include "shm__monitor.h" @@ -685,6 +686,12 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe dds_topic_allow_set_qos (tp); dds_topic_unpin (tp); dds_subscriber_unlock (sub); + +#ifdef DDS_HAS_LTTNG_TRACING + dds_guid_t guid; + (void)dds_get_guid(reader, &guid); + TRACEPOINT(create_reader, (const void *)rd, rd->m_topic->m_name, guid.v); +#endif return reader; #ifdef DDS_HAS_SECURITY diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index b2afa1373b..188d599fbf 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -26,6 +26,7 @@ #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_deliver_locally.h" +#include "tracing_lttng.h" #ifdef DDS_HAS_SHM #include "dds/ddsi/shm_sync.h" @@ -333,6 +334,8 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam if (data == NULL) return DDS_RETCODE_BAD_PARAMETER; + TRACEPOINT(write, (const void *)wr, data, tstamp); + /* Check for topic filter */ if (!writekey && wr->m_topic->m_filter.mode != DDS_TOPIC_FILTER_NONE) { diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index b1d6f1f8bd..e9fead3679 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -34,6 +34,7 @@ #include "dds__statistics.h" #include "dds__data_allocator.h" #include "dds/ddsi/ddsi_statistics.h" +#include "tracing_lttng.h" DECL_ENTITY_LOCK_UNLOCK (dds_writer) @@ -445,6 +446,12 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit nn_xpack_sendq_start(gv); } ddsrt_mutex_unlock (&gv->sendq_running_lock); + +#ifdef DDS_HAS_LTTNG_TRACING + dds_guid_t guid; + (void)dds_get_guid(writer, &guid); + TRACEPOINT(create_writer, (const void *)wr, wr->m_topic->m_name, guid.v); +#endif return writer; #ifdef DDS_HAS_SECURITY diff --git a/src/core/ddsc/src/tracing_lttng.c b/src/core/ddsc/src/tracing_lttng.c new file mode 100644 index 0000000000..5deca530ce --- /dev/null +++ b/src/core/ddsc/src/tracing_lttng.c @@ -0,0 +1,16 @@ +/* + * Copyright(c) 2021 Christophe Bedard + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#define TRACEPOINT_CREATE_PROBES + +#define TRACEPOINT_DEFINE +#include "tracing_lttng.h" diff --git a/src/core/ddsc/src/tracing_lttng.h b/src/core/ddsc/src/tracing_lttng.h new file mode 100644 index 0000000000..eb102dd7d0 --- /dev/null +++ b/src/core/ddsc/src/tracing_lttng.h @@ -0,0 +1,117 @@ +/* + * Copyright(c) 2021 Christophe Bedard + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +// Provide fake header guard for cpplint +#undef _DDS_LTTNG_H_ +#ifndef _DDS_LTTNG_H_ +#define _DDS_LTTNG_H_ + +#include "dds/features.h" + +#ifndef DDS_HAS_LTTNG_TRACING + +#define TRACEPOINT(event_name, ...) ((void) (0)) + +#else // DDS_HAS_LTTNG_TRACING + +#undef TRACEPOINT_PROVIDER +#define TRACEPOINT_PROVIDER dds + +#define TRACEPOINT(event_name, ...) \ + tracepoint(TRACEPOINT_PROVIDER, event_name, __VA_ARGS__) + +#undef TRACEPOINT_INCLUDE +#define TRACEPOINT_INCLUDE "tracing_lttng.h" + +#if !defined(__DDS_LTTNG_H_) || defined(TRACEPOINT_HEADER_MULTI_READ) +#define __DDS_LTTNG_H_ + +#include + +#ifndef LTTNG_UST_HAVE_SDT_INTEGRATION +# ifdef _MSC_VER +# pragma message ("lttng-ust has not been configured & built with SDT integration (--with-sdt)") +# else +# warning lttng-ust has not been configured & built with SDT integration (--with-sdt) +# endif +#endif + +#include +#include + +#define DDS_GID_STORAGE_SIZE 16u + +TRACEPOINT_EVENT( + TRACEPOINT_PROVIDER, + create_writer, + TP_ARGS( + const void *, writer_arg, + char *, topic_name_arg, + const uint8_t *, gid_arg + ), + TP_FIELDS( + ctf_integer_hex(const void *, writer, writer_arg) + ctf_string(topic_name, topic_name_arg) + ctf_array(uint8_t, gid, gid_arg, DDS_GID_STORAGE_SIZE) + ) +) + +TRACEPOINT_EVENT( + TRACEPOINT_PROVIDER, + create_reader, + TP_ARGS( + const void *, reader_arg, + char *, topic_name_arg, + const uint8_t *, gid_arg + ), + TP_FIELDS( + ctf_integer_hex(const void *, reader, reader_arg) + ctf_string(topic_name, topic_name_arg) + ctf_array(uint8_t, gid, gid_arg, DDS_GID_STORAGE_SIZE) + ) +) + +TRACEPOINT_EVENT( + TRACEPOINT_PROVIDER, + write, + TP_ARGS( + const void *, writer_arg, + const void *, data_arg, + int64_t, timestamp_arg + ), + TP_FIELDS( + ctf_integer_hex(const void *, writer, writer_arg) + ctf_integer_hex(const void *, data, data_arg) + ctf_integer(int64_t, timestamp, timestamp_arg) + ) +) + +TRACEPOINT_EVENT( + TRACEPOINT_PROVIDER, + read, + TP_ARGS( + const void *, reader_arg, + const void *, buffer_arg + ), + TP_FIELDS( + ctf_integer_hex(const void *, reader, reader_arg) + ctf_integer_hex(const void *, buffer, buffer_arg) + ) +) + +#endif // __DDS_LTTNG_H_ + +#include + +#endif // DDS_HAS_LTTNG_TRACING + +#endif // _DDS_LTTNG_H_ diff --git a/src/features.h.in b/src/features.h.in index 0350bb05f1..532e4f8626 100644 --- a/src/features.h.in +++ b/src/features.h.in @@ -39,4 +39,7 @@ /* Whether or not support for Iceoryx support is included */ #cmakedefine DDS_HAS_SHM @DDS_HAS_SHM@ +/* Whether or not support for LTTng tracing instrumentation is included */ +#cmakedefine DDS_HAS_LTTNG_TRACING @DDS_HAS_LTTNG_TRACING@ + #endif From 21d447ca963ccc210f13605497a911c842d6ade1 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Mon, 9 Aug 2021 11:12:57 -0400 Subject: [PATCH 37/37] Remove -rdynamic Signed-off-by: Christophe Bedard --- src/core/ddsc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index dd2318cc64..206987b462 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -121,7 +121,7 @@ target_include_directories(ddsc $) if (DDS_HAS_LTTNG_TRACING) - target_link_libraries(ddsc PRIVATE ${LTTNG_LIBRARIES} "-rdynamic") + target_link_libraries(ddsc PRIVATE ${LTTNG_LIBRARIES}) endif() install(