This is an automated email from the ASF dual-hosted git repository. fgerlits pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit 5eda82dc1f5432fea40458961f8e65f5555bc05c Author: Gabor Gyimesi <[email protected]> AuthorDate: Tue Apr 15 09:15:16 2025 +0200 MINIFICPP-2563 Add build option for enabling link time optimization Signed-off-by: Ferenc Gerlits <[email protected]> Closes #1963 --- CMakeLists.txt | 14 ++++++++ bootstrap.sh | 7 ++++ bstrp_functions.sh | 11 ++++--- cmake/MiNiFiOptions.cmake | 1 + .../tests/ProcessContextExprTests.cpp | 38 +++++++++++----------- .../rocksdb-repos/database/RocksDatabase.cpp | 17 +++++----- extensions/rocksdb-repos/database/RocksDatabase.h | 2 -- .../rocksdb-repos/database/RocksDbInstance.cpp | 5 ++- .../rocksdb-repos/database/RocksDbInstance.h | 2 +- .../tests/unit/ManifestTests.cpp | 6 ++-- libminifi/src/agent/agent_docs.cpp | 9 +++-- 11 files changed, 68 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fae0cc88c..b2ecde8c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,20 @@ if (MINIFI_ADVANCED_CODE_COVERAGE) append_coverage_compiler_flags() endif() +if (MINIFI_ADVANCED_LINK_TIME_OPTIMIZATION) + if (WIN32) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /GL") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GL") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LTCG") + else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto") + endif() +endif() + #### Third party dependencies #### # Define function for passing dependencies diff --git a/bootstrap.sh b/bootstrap.sh index e0113df11..08de26be8 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -324,6 +324,7 @@ USE_SHARED_LIBS=${TRUE} ASAN_ENABLED=${FALSE} MINIFI_FAIL_ON_WARNINGS=${FALSE} TESTS_ENABLED=${TRUE} +LTO_ENABLED=${FALSE} ## name, default, values add_multi_option BUILD_PROFILE "RelWithDebInfo" "RelWithDebInfo" "Debug" "MinSizeRel" "Release" @@ -474,6 +475,12 @@ build_cmake_command(){ CMAKE_BUILD_COMMAND="${CMAKE_BUILD_COMMAND} -DMINIFI_FAIL_ON_WARNINGS=OFF" fi + if [ "${LTO_ENABLED}" = "${TRUE}" ]; then + CMAKE_BUILD_COMMAND="${CMAKE_BUILD_COMMAND} -DMINIFI_ADVANCED_LINK_TIME_OPTIMIZATION=ON " + else + CMAKE_BUILD_COMMAND="${CMAKE_BUILD_COMMAND} -DMINIFI_ADVANCED_LINK_TIME_OPTIMIZATION=OFF" + fi + CMAKE_BUILD_COMMAND="${CMAKE_BUILD_COMMAND} -DBUILD_IDENTIFIER=${BUILD_IDENTIFIER}" CMAKE_BUILD_COMMAND="${CMAKE_BUILD_COMMAND} -DCMAKE_BUILD_TYPE=${BUILD_PROFILE}" diff --git a/bstrp_functions.sh b/bstrp_functions.sh index f78220a9d..4783a8d27 100755 --- a/bstrp_functions.sh +++ b/bstrp_functions.sh @@ -183,6 +183,7 @@ save_state(){ echo_state_variable USE_SHARED_LIBS echo_state_variable ASAN_ENABLED echo_state_variable MINIFI_FAIL_ON_WARNINGS + echo_state_variable LTO_ENABLED for option in "${OPTIONS[@]}" ; do echo_state_variable "${option}" done @@ -408,10 +409,11 @@ show_supported_features() { echo "****************************************" echo "1. Enable Tests ................$(print_feature_status TESTS_ENABLED)" echo "2. Enable all extensions" - echo "4. Use Shared Dependency Links .$(print_feature_status USE_SHARED_LIBS)" - echo "5. Build Profile ...............$(print_multi_option_status BUILD_PROFILE)" - echo "6. Create ASAN build ...........$(print_feature_status ASAN_ENABLED)" - echo "7. Treat warnings as errors.....$(print_feature_status MINIFI_FAIL_ON_WARNINGS)" + echo "4. Use Shared Dependency Links ...$(print_feature_status USE_SHARED_LIBS)" + echo "5. Build Profile .................$(print_multi_option_status BUILD_PROFILE)" + echo "6. Create ASAN build .............$(print_feature_status ASAN_ENABLED)" + echo "7. Treat warnings as errors.......$(print_feature_status MINIFI_FAIL_ON_WARNINGS)" + echo "8. Enable link time optimization .$(print_feature_status LTO_ENABLED)" echo "P. Continue with these options" if [ "$GUIDED_INSTALL" = "${TRUE}" ]; then echo "R. Return to Main Menu" @@ -458,6 +460,7 @@ read_feature_options(){ 5) ToggleMultiOption BUILD_PROFILE;; 6) ToggleFeature ASAN_ENABLED;; 7) ToggleFeature MINIFI_FAIL_ON_WARNINGS;; + 8) ToggleFeature LTO_ENABLED;; p) export FEATURES_SELECTED="true" ;; r) if [ "$GUIDED_INSTALL" = "${TRUE}" ]; then export MENU="main" diff --git a/cmake/MiNiFiOptions.cmake b/cmake/MiNiFiOptions.cmake index 8fb152b33..9503d8a0f 100644 --- a/cmake/MiNiFiOptions.cmake +++ b/cmake/MiNiFiOptions.cmake @@ -72,6 +72,7 @@ add_minifi_option(AWS_ENABLE_UNITY_BUILD "If enabled, AWS SDK libraries will be add_minifi_dependent_option(MINIFI_ADVANCED_ASAN_BUILD "Uses AddressSanitizer to instrument the code" OFF "NOT WIN32" OFF) add_minifi_dependent_option(MINIFI_ADVANCED_CODE_COVERAGE "Use coverage build options and enable coverage build target" OFF "NOT WIN32" OFF) +add_minifi_option(MINIFI_ADVANCED_LINK_TIME_OPTIMIZATION "Use link time optimization" OFF) if (WIN32) add_minifi_option(MINIFI_INCLUDE_VC_REDIST_MERGE_MODULES "Include merge modules for Visual C++ Redistributable with the MSI generated by CPack. The resulting MSI is not distributable under Apache 2.0." OFF) diff --git a/extensions/expression-language/tests/ProcessContextExprTests.cpp b/extensions/expression-language/tests/ProcessContextExprTests.cpp index 0537cb7a8..07133b31d 100644 --- a/extensions/expression-language/tests/ProcessContextExprTests.cpp +++ b/extensions/expression-language/tests/ProcessContextExprTests.cpp @@ -30,7 +30,7 @@ namespace org::apache::nifi::minifi { -class DummyProcessor : public core::ProcessorImpl { +class DummyProcessContextExprProcessor : public core::ProcessorImpl { public: using core::ProcessorImpl::ProcessorImpl; @@ -53,50 +53,50 @@ class DummyProcessor : public core::ProcessorImpl { void initialize() override { setSupportedProperties(Properties); } }; -REGISTER_RESOURCE(DummyProcessor, Processor); +REGISTER_RESOURCE(DummyProcessContextExprProcessor, Processor); } // namespace org::apache::nifi::minifi TEST_CASE("ProcessContextExpr can update existing processor properties", "[setProperty][getProperty]") { TestController test_controller; std::shared_ptr<TestPlan> test_plan = test_controller.createPlan(); - [[maybe_unused]] minifi::core::Processor* dummy_processor = test_plan->addProcessor("DummyProcessor", "dummy_processor"); + [[maybe_unused]] minifi::core::Processor* dummy_processor = test_plan->addProcessor("DummyProcessContextExprProcessor", "dummy_processor"); std::shared_ptr<minifi::core::ProcessContext> context = [test_plan] { test_plan->runNextProcessor(); return test_plan->getCurrentContext(); }(); REQUIRE(dynamic_pointer_cast<minifi::core::ProcessContextExpr>(context) != nullptr); SECTION("Set and get simple property") { SECTION("Using a Property reference parameter") { - REQUIRE(context->setProperty(minifi::DummyProcessor::SimpleProperty, "foo")); - CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, nullptr) == "foo"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, "foo")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, nullptr) == "foo"); - REQUIRE(context->setProperty(minifi::DummyProcessor::SimpleProperty, "bar")); - CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, nullptr) == "bar"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, "bar")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, nullptr) == "bar"); } SECTION("Using a string parameter") { - REQUIRE(context->setProperty(minifi::DummyProcessor::SimpleProperty, "foo")); - CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, nullptr) == "foo"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, "foo")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, nullptr) == "foo"); - REQUIRE(context->setProperty(minifi::DummyProcessor::SimpleProperty, "bar")); - CHECK(context->getProperty(minifi::DummyProcessor::SimpleProperty, nullptr) == "bar"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, "bar")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::SimpleProperty, nullptr) == "bar"); } } SECTION("Set and get expression language property") { SECTION("Using a Property reference parameter") { - REQUIRE(context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty, "foo")); - CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, nullptr) == "foo"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, "foo")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, nullptr) == "foo"); - REQUIRE(context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty, "bar")); - CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, nullptr) == "bar"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, "bar")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, nullptr) == "bar"); } SECTION("Using a string parameter") { - REQUIRE(context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty, "foo")); - CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, nullptr) == "foo"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, "foo")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, nullptr) == "foo"); - REQUIRE(context->setProperty(minifi::DummyProcessor::ExpressionLanguageProperty, "bar")); - CHECK(context->getProperty(minifi::DummyProcessor::ExpressionLanguageProperty, nullptr) == "bar"); + REQUIRE(context->setProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, "bar")); + CHECK(context->getProperty(minifi::DummyProcessContextExprProcessor::ExpressionLanguageProperty, nullptr) == "bar"); } } } diff --git a/extensions/rocksdb-repos/database/RocksDatabase.cpp b/extensions/rocksdb-repos/database/RocksDatabase.cpp index df1c597cc..1ab89f83c 100644 --- a/extensions/rocksdb-repos/database/RocksDatabase.cpp +++ b/extensions/rocksdb-repos/database/RocksDatabase.cpp @@ -27,32 +27,31 @@ namespace org::apache::nifi::minifi::internal { -std::shared_ptr<core::logging::Logger> RocksDatabase::logger_ = core::logging::LoggerFactory<RocksDatabase>::getLogger(); - std::unique_ptr<RocksDatabase> RocksDatabase::create(const DBOptionsPatch& db_options_patch, const ColumnFamilyOptionsPatch& cf_options_patch, const std::string& uri, const std::unordered_map<std::string, std::string>& db_config_override, RocksDbMode mode) { const std::string scheme = "minifidb://"; - logger_->log_info("Acquiring database handle '{}'", uri); + auto logger = core::logging::LoggerFactory<RocksDatabase>::getLogger(); + logger->log_info("Acquiring database handle '{}'", uri); std::string db_path = uri; std::string db_column = "default"; if (utils::string::startsWith(uri, scheme)) { const std::string path = uri.substr(scheme.length()); - logger_->log_info("RocksDB scheme is detected in '{}'", uri); + logger->log_info("RocksDB scheme is detected in '{}'", uri); // last segment is treated as the column name std::string::size_type pos = path.find_last_of('/'); if (pos == std::string::npos) { pos = path.find_last_of('\\'); } if (pos == std::string::npos) { - logger_->log_error("Couldn't detect the column name in '{}'", uri); + logger->log_error("Couldn't detect the column name in '{}'", uri); return nullptr; } db_path = path.substr(0, pos); db_column = path.substr(pos + 1); - logger_->log_info("Using column '{}' in rocksdb database '{}'", db_column, db_path); + logger->log_info("Using column '{}' in rocksdb database '{}'", db_column, db_path); } else { - logger_->log_info("Simple directory detected '{}', using as is", uri); + logger->log_info("Simple directory detected '{}', using as is", uri); } if (mode == RocksDbMode::ReadOnly) { @@ -68,11 +67,11 @@ std::unique_ptr<RocksDatabase> RocksDatabase::create(const DBOptionsPatch& db_op std::lock_guard<std::mutex> guard(mtx); instance = databases[db_path].lock(); if (!instance) { - logger_->log_info("Opening rocksdb database '{}'", db_path); + logger->log_info("Opening rocksdb database '{}'", db_path); instance = std::make_shared<RocksDbInstance>(db_path, mode); databases[db_path] = instance; } else { - logger_->log_info("Using previously opened rocksdb instance '{}'", db_path); + logger->log_info("Using previously opened rocksdb instance '{}'", db_path); } } return std::make_unique<RocksDatabase>(instance, db_column, db_options_patch, cf_options_patch, db_config_override); diff --git a/extensions/rocksdb-repos/database/RocksDatabase.h b/extensions/rocksdb-repos/database/RocksDatabase.h index afab4f844..175d0cb21 100644 --- a/extensions/rocksdb-repos/database/RocksDatabase.h +++ b/extensions/rocksdb-repos/database/RocksDatabase.h @@ -59,8 +59,6 @@ class RocksDatabase { private: const std::string column_; std::shared_ptr<RocksDbInstance> db_; - - static std::shared_ptr<core::logging::Logger> logger_; }; } // namespace org::apache::nifi::minifi::internal diff --git a/extensions/rocksdb-repos/database/RocksDbInstance.cpp b/extensions/rocksdb-repos/database/RocksDbInstance.cpp index a08311573..9601bd46f 100644 --- a/extensions/rocksdb-repos/database/RocksDbInstance.cpp +++ b/extensions/rocksdb-repos/database/RocksDbInstance.cpp @@ -27,9 +27,8 @@ namespace org::apache::nifi::minifi::internal { -std::shared_ptr<core::logging::Logger> RocksDbInstance::logger_ = core::logging::LoggerFactory<RocksDbInstance>::getLogger(); - -RocksDbInstance::RocksDbInstance(std::string path, RocksDbMode mode) : db_name_(std::move(path)), mode_(mode) {} +RocksDbInstance::RocksDbInstance(std::string path, RocksDbMode mode) : db_name_(std::move(path)), mode_(mode), logger_(core::logging::LoggerFactory<RocksDbInstance>::getLogger()) { +} void RocksDbInstance::invalidate() { std::lock_guard<std::mutex> db_guard{mtx_}; diff --git a/extensions/rocksdb-repos/database/RocksDbInstance.h b/extensions/rocksdb-repos/database/RocksDbInstance.h index c6bfbe241..c29240219 100644 --- a/extensions/rocksdb-repos/database/RocksDbInstance.h +++ b/extensions/rocksdb-repos/database/RocksDbInstance.h @@ -76,7 +76,7 @@ class RocksDbInstance { std::unordered_map<std::string, ColumnConfig> column_configs_; - static std::shared_ptr<core::logging::Logger> logger_; + std::shared_ptr<core::logging::Logger> logger_; }; } // namespace org::apache::nifi::minifi::internal diff --git a/extensions/standard-processors/tests/unit/ManifestTests.cpp b/extensions/standard-processors/tests/unit/ManifestTests.cpp index 2e04ca3db..2ba13b0ef 100644 --- a/extensions/standard-processors/tests/unit/ManifestTests.cpp +++ b/extensions/standard-processors/tests/unit/ManifestTests.cpp @@ -69,9 +69,9 @@ TEST_CASE("Test Valid Regex", "[validRegex]") { REQUIRE_FALSE(resp.children.empty()); const auto &processors = resp.children[0]; REQUIRE_FALSE(processors.children.empty()); - const auto &proc_0 = processors.children[0]; - REQUIRE_FALSE(proc_0.children.empty()); - const auto &prop_descriptors = proc_0.children[0]; + const auto &processor_with_properties = "org.apache.nifi.minifi.processors.UpdateAttribute" != processors.children[0].name ? processors.children[0] : processors.children[1]; + REQUIRE_FALSE(processor_with_properties.children.empty()); + const auto &prop_descriptors = processor_with_properties.children[0]; REQUIRE_FALSE(prop_descriptors.children.empty()); const auto &prop_0 = prop_descriptors.children[0]; REQUIRE(prop_0.children.size() >= 7); diff --git a/libminifi/src/agent/agent_docs.cpp b/libminifi/src/agent/agent_docs.cpp index 30f1b9a9b..9f6b58624 100644 --- a/libminifi/src/agent/agent_docs.cpp +++ b/libminifi/src/agent/agent_docs.cpp @@ -20,15 +20,18 @@ namespace org::apache::nifi::minifi { namespace { -std::map<std::string, Components> AgentDocs_class_mappings; +std::map<std::string, Components>& getAgentDocsClassMappings() { + static std::map<std::string, Components> mappings; + return mappings; +} } // namespace const std::map<std::string, Components>& AgentDocs::getClassDescriptions() { - return AgentDocs_class_mappings; + return getAgentDocsClassMappings(); } std::map<std::string, Components>& AgentDocs::getMutableClassDescriptions() { - return AgentDocs_class_mappings; + return getAgentDocsClassMappings(); }
