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();
 }
 
 

Reply via email to