You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ad...@apache.org on 2022/04/01 10:58:26 UTC

[nifi-minifi-cpp] branch main updated (d1aa2a5 -> 4700087)

This is an automated email from the ASF dual-hosted git repository.

adebreceni pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git.


    from d1aa2a5  MINIFICPP-1790 - Change default agent property update lifetime
     new bc46482  MINIFICPP-1779 Verify multiple C2 commands in HB response
     new aa65430  MINIFICPP-1783 Encrypted values in agent manifest should remain in encrypted form
     new 163c7c2  MINIFICPP-1789 - Log checking is wrong in integration tests
     new 1d3b2fc  MINIFICPP-1792 Fix build with cmake 3.23.0
     new 4700087  MINIFICPP-1788 flush old bins on expiration

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 cmake/BundledAwsSdkCpp.cmake                       |  60 +++++-----
 cmake/BundledAzureSdkCpp.cmake                     |  24 ++--
 cmake/BundledCivetWeb.cmake                        |  10 +-
 cmake/BundledLibSSH2.cmake                         |   4 +-
 cmake/BundledLibcURL.cmake                         |   4 +-
 cmake/BundledOpen62541.cmake                       |   4 +-
 cmake/BundledOpenCV.cmake                          |  64 +++++-----
 cmake/BundledRocksDB.cmake                         |   4 +-
 cmake/BundledSpdlog.cmake                          |   6 +-
 cmake/BundledYamlCpp.cmake                         |   8 +-
 .../integration/MiNiFi_integration_test_driver.py  |   4 +-
 docker/test/integration/features/mqtt.feature      |   6 +-
 docker/test/integration/steps/steps.py             |   4 +-
 .../http-curl/tests/C2DescribeManifestTest.cpp     |  10 ++
 .../http-curl/tests/C2MultipleCommandsTest.cpp     | 130 +++++++++++++++++++++
 extensions/http-curl/tests/CMakeLists.txt          |   1 +
 extensions/http-curl/tests/HTTPHandlers.h          |  65 +++++++----
 extensions/libarchive/BinFiles.cpp                 |   2 +
 libminifi/src/FlowController.cpp                   |   2 +-
 libminifi/src/c2/C2Client.cpp                      |   2 +-
 libminifi/test/integration/IntegrationBase.h       |   4 +
 21 files changed, 303 insertions(+), 115 deletions(-)
 create mode 100644 extensions/http-curl/tests/C2MultipleCommandsTest.cpp

[nifi-minifi-cpp] 04/05: MINIFICPP-1792 Fix build with cmake 3.23.0

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adebreceni pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 1d3b2fcbfad7baba50e045748f27c4c900517310
Author: Gabor Gyimesi <ga...@gmail.com>
AuthorDate: Fri Apr 1 12:55:49 2022 +0200

    MINIFICPP-1792 Fix build with cmake 3.23.0
    
    Signed-off-by: Adam Debreceni <ad...@apache.org>
    
    This closes #1292
---
 cmake/BundledAwsSdkCpp.cmake   | 60 ++++++++++++++++++++-------------------
 cmake/BundledAzureSdkCpp.cmake | 24 ++++++++--------
 cmake/BundledCivetWeb.cmake    | 10 +++----
 cmake/BundledLibSSH2.cmake     |  4 ++-
 cmake/BundledLibcURL.cmake     |  4 ++-
 cmake/BundledOpen62541.cmake   |  4 ++-
 cmake/BundledOpenCV.cmake      | 64 ++++++++++++++++++++++--------------------
 cmake/BundledRocksDB.cmake     |  4 ++-
 cmake/BundledSpdlog.cmake      |  6 ++--
 cmake/BundledYamlCpp.cmake     |  8 ++++--
 10 files changed, 103 insertions(+), 85 deletions(-)

diff --git a/cmake/BundledAwsSdkCpp.cmake b/cmake/BundledAwsSdkCpp.cmake
index 8960bf9..aeb072c 100644
--- a/cmake/BundledAwsSdkCpp.cmake
+++ b/cmake/BundledAwsSdkCpp.cmake
@@ -25,9 +25,11 @@ function(use_bundled_libaws SOURCE_DIR BINARY_DIR)
             (\"${Patch_EXECUTABLE}\" -p1 -R -s -f --dry-run -i \"${PATCH_FILE3}\" || \"${Patch_EXECUTABLE}\" -p1 -N -i \"${PATCH_FILE3}\") ")
 
     if (WIN32)
-        set(CMAKE_INSTALL_LIBDIR "lib")
+        set(LIBDIR "lib")
     else()
         include(GNUInstallDirs)
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
     endif()
 
     # Define byproducts
@@ -40,22 +42,22 @@ function(use_bundled_libaws SOURCE_DIR BINARY_DIR)
     endif()
 
     if (NOT WIN32 AND NOT APPLE)
-        list(APPEND BYPRODUCTS "${CMAKE_INSTALL_LIBDIR}/${PREFIX}s2n.${SUFFIX}")
+        list(APPEND BYPRODUCTS "${LIBDIR}/${PREFIX}s2n.${SUFFIX}")
     endif()
     list(APPEND BYPRODUCTS
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-checksums.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-event-stream.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-s3.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-crt-cpp.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-common.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-mqtt.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-io.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-http.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-auth.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-cal.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-compression.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-cpp-sdk-core.${SUFFIX}"
-            "${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-cpp-sdk-s3.${SUFFIX}")
+            "${LIBDIR}/${PREFIX}aws-checksums.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-event-stream.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-s3.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-crt-cpp.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-common.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-mqtt.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-io.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-http.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-auth.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-cal.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-c-compression.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-cpp-sdk-core.${SUFFIX}"
+            "${LIBDIR}/${PREFIX}aws-cpp-sdk-s3.${SUFFIX}")
 
     FOREACH(BYPRODUCT ${BYPRODUCTS})
         LIST(APPEND AWSSDK_LIBRARIES_LIST "${BINARY_DIR}/thirdparty/libaws-install/${BYPRODUCT}")
@@ -103,19 +105,19 @@ function(use_bundled_libaws SOURCE_DIR BINARY_DIR)
     file(MAKE_DIRECTORY ${LIBAWS_INCLUDE_DIR})
 
     add_library(AWS::aws-c-common STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-common PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-common.${SUFFIX}")
+    set_target_properties(AWS::aws-c-common PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-common.${SUFFIX}")
     add_dependencies(AWS::aws-c-common aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-common INTERFACE ${LIBAWS_INCLUDE_DIR})
 
     if (NOT WIN32 AND NOT APPLE)
         add_library(AWS::s2n STATIC IMPORTED)
-        set_target_properties(AWS::s2n PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}s2n.${SUFFIX}")
+        set_target_properties(AWS::s2n PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}s2n.${SUFFIX}")
         add_dependencies(AWS::s2n aws-sdk-cpp-external)
         target_include_directories(AWS::s2n INTERFACE ${LIBAWS_INCLUDE_DIR})
     endif()
 
     add_library(AWS::aws-c-io STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-io PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-io.${SUFFIX}")
+    set_target_properties(AWS::aws-c-io PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-io.${SUFFIX}")
     add_dependencies(AWS::aws-c-io aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-io INTERFACE ${LIBAWS_INCLUDE_DIR})
     target_link_libraries(AWS::aws-c-io INTERFACE AWS::aws-c-common)
@@ -124,55 +126,55 @@ function(use_bundled_libaws SOURCE_DIR BINARY_DIR)
     endif()
 
     add_library(AWS::aws-checksums STATIC IMPORTED)
-    set_target_properties(AWS::aws-checksums PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-checksums.${SUFFIX}")
+    set_target_properties(AWS::aws-checksums PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-checksums.${SUFFIX}")
     add_dependencies(AWS::aws-checksums aws-sdk-cpp-external)
     target_include_directories(AWS::aws-checksums INTERFACE ${LIBAWS_INCLUDE_DIR})
 
     add_library(AWS::aws-c-event-stream STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-event-stream PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-event-stream.${SUFFIX}")
+    set_target_properties(AWS::aws-c-event-stream PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-event-stream.${SUFFIX}")
     add_dependencies(AWS::aws-c-event-stream aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-event-stream INTERFACE ${LIBAWS_INCLUDE_DIR})
     target_link_libraries(AWS::aws-c-event-stream INTERFACE AWS::aws-checksums AWS::aws-c-io)
 
     add_library(AWS::aws-c-auth STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-auth PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-auth.${SUFFIX}")
+    set_target_properties(AWS::aws-c-auth PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-auth.${SUFFIX}")
     add_dependencies(AWS::aws-c-auth aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-auth INTERFACE ${LIBAWS_INCLUDE_DIR})
 
     add_library(AWS::aws-c-s3 STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-s3 PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-s3.${SUFFIX}")
+    set_target_properties(AWS::aws-c-s3 PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-s3.${SUFFIX}")
     add_dependencies(AWS::aws-c-s3 aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-s3 INTERFACE ${LIBAWS_INCLUDE_DIR})
     target_link_libraries(AWS::aws-c-s3 INTERFACE AWS::aws-c-auth)
 
     add_library(AWS::aws-c-mqtt STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-mqtt PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-mqtt.${SUFFIX}")
+    set_target_properties(AWS::aws-c-mqtt PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-mqtt.${SUFFIX}")
     add_dependencies(AWS::aws-c-mqtt aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-mqtt INTERFACE ${LIBAWS_INCLUDE_DIR})
 
     add_library(AWS::aws-c-http STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-http PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-http.${SUFFIX}")
+    set_target_properties(AWS::aws-c-http PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-http.${SUFFIX}")
     add_dependencies(AWS::aws-c-http aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-http INTERFACE ${LIBAWS_INCLUDE_DIR})
 
     add_library(AWS::aws-c-cal STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-cal PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-cal.${SUFFIX}")
+    set_target_properties(AWS::aws-c-cal PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-cal.${SUFFIX}")
     add_dependencies(AWS::aws-c-cal aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-cal INTERFACE ${LIBAWS_INCLUDE_DIR})
 
     add_library(AWS::aws-c-compression STATIC IMPORTED)
-    set_target_properties(AWS::aws-c-compression PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-c-compression.${SUFFIX}")
+    set_target_properties(AWS::aws-c-compression PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-c-compression.${SUFFIX}")
     add_dependencies(AWS::aws-c-compression aws-sdk-cpp-external)
     target_include_directories(AWS::aws-c-compression INTERFACE ${LIBAWS_INCLUDE_DIR})
 
     add_library(AWS::aws-crt-cpp STATIC IMPORTED)
-    set_target_properties(AWS::aws-crt-cpp PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-crt-cpp.${SUFFIX}")
+    set_target_properties(AWS::aws-crt-cpp PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-crt-cpp.${SUFFIX}")
     add_dependencies(AWS::aws-crt-cpp aws-sdk-cpp-external)
     target_include_directories(AWS::aws-crt-cpp INTERFACE ${LIBAWS_INCLUDE_DIR})
     target_link_libraries(AWS::aws-crt-cpp INTERFACE AWS::aws-c-io AWS::aws-c-s3 AWS::aws-c-mqtt AWS::aws-c-http AWS::aws-c-cal AWS::aws-c-compression)
 
     add_library(AWS::aws-cpp-sdk-core STATIC IMPORTED)
-    set_target_properties(AWS::aws-cpp-sdk-core PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-cpp-sdk-core.${SUFFIX}")
+    set_target_properties(AWS::aws-cpp-sdk-core PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-cpp-sdk-core.${SUFFIX}")
     add_dependencies(AWS::aws-cpp-sdk-core aws-sdk-cpp-external)
     target_include_directories(AWS::aws-cpp-sdk-core INTERFACE ${LIBAWS_INCLUDE_DIR})
     target_link_libraries(AWS::aws-cpp-sdk-core INTERFACE AWS::aws-crt-cpp AWS::aws-c-event-stream CURL::libcurl OpenSSL::Crypto OpenSSL::SSL ZLIB::ZLIB Threads::Threads)
@@ -185,7 +187,7 @@ function(use_bundled_libaws SOURCE_DIR BINARY_DIR)
     endif()
 
     add_library(AWS::aws-cpp-sdk-s3 STATIC IMPORTED)
-    set_target_properties(AWS::aws-cpp-sdk-s3 PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${CMAKE_INSTALL_LIBDIR}/${PREFIX}aws-cpp-sdk-s3.${SUFFIX}")
+    set_target_properties(AWS::aws-cpp-sdk-s3 PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/thirdparty/libaws-install/${LIBDIR}/${PREFIX}aws-cpp-sdk-s3.${SUFFIX}")
     add_dependencies(AWS::aws-cpp-sdk-s3 aws-sdk-cpp-external)
     target_include_directories(AWS::aws-cpp-sdk-s3 INTERFACE ${LIBAWS_INCLUDE_DIR})
     target_link_libraries(AWS::aws-cpp-sdk-s3 INTERFACE AWS::aws-cpp-sdk-core)
diff --git a/cmake/BundledAzureSdkCpp.cmake b/cmake/BundledAzureSdkCpp.cmake
index ed3d318..847b2c7 100644
--- a/cmake/BundledAzureSdkCpp.cmake
+++ b/cmake/BundledAzureSdkCpp.cmake
@@ -22,26 +22,28 @@ function(use_bundled_libazure SOURCE_DIR BINARY_DIR)
     # Define byproducts
     set(INSTALL_DIR "${BINARY_DIR}/thirdparty/azure-sdk-cpp-install")
     if (WIN32)
-        set(CMAKE_INSTALL_LIBDIR "lib")
+        set(LIBDIR "lib")
     else()
         include(GNUInstallDirs)
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
     endif()
     if (WIN32)
         set(SUFFIX "lib")
         set(PREFIX "")
-        set(AZURE_CORE_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-core.${SUFFIX}")
-        set(AZURE_STORAGE_COMMON_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-storage-common.${SUFFIX}")
-        set(AZURE_STORAGE_BLOBS_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-storage-blobs.${SUFFIX}")
-        set(AZURE_IDENTITY_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-identity.${SUFFIX}")
-        set(AZURE_STORAGE_FILES_DATALAKE_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-storage-files-datalake.${SUFFIX}")
+        set(AZURE_CORE_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-core.${SUFFIX}")
+        set(AZURE_STORAGE_COMMON_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-storage-common.${SUFFIX}")
+        set(AZURE_STORAGE_BLOBS_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-storage-blobs.${SUFFIX}")
+        set(AZURE_IDENTITY_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-identity.${SUFFIX}")
+        set(AZURE_STORAGE_FILES_DATALAKE_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-storage-files-datalake.${SUFFIX}")
     else()
         set(SUFFIX "a")
         set(PREFIX "lib")
-        set(AZURE_CORE_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-core.${SUFFIX}")
-        set(AZURE_STORAGE_COMMON_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-storage-common.${SUFFIX}")
-        set(AZURE_STORAGE_BLOBS_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-storage-blobs.${SUFFIX}")
-        set(AZURE_IDENTITY_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-identity.${SUFFIX}")
-        set(AZURE_STORAGE_FILES_DATALAKE_LIB "${INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}azure-storage-files-datalake.${SUFFIX}")
+        set(AZURE_CORE_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-core.${SUFFIX}")
+        set(AZURE_STORAGE_COMMON_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-storage-common.${SUFFIX}")
+        set(AZURE_STORAGE_BLOBS_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-storage-blobs.${SUFFIX}")
+        set(AZURE_IDENTITY_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-identity.${SUFFIX}")
+        set(AZURE_STORAGE_FILES_DATALAKE_LIB "${INSTALL_DIR}/${LIBDIR}/${PREFIX}azure-storage-files-datalake.${SUFFIX}")
     endif()
 
     set(AZURESDK_LIBRARIES_LIST
diff --git a/cmake/BundledCivetWeb.cmake b/cmake/BundledCivetWeb.cmake
index c030ce7..b4581bc 100644
--- a/cmake/BundledCivetWeb.cmake
+++ b/cmake/BundledCivetWeb.cmake
@@ -26,11 +26,11 @@ function(use_bundled_civetweb SOURCE_DIR BINARY_DIR)
     if (WIN32)
         set(SUFFIX "lib")
     else()
-		set(PREFIX "lib")
-      include(GNUInstallDirs)
-      set(LIBDIR "${CMAKE_INSTALL_LIBDIR}")
-      set(SUFFIX "a")
-
+        set(PREFIX "lib")
+        include(GNUInstallDirs)
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
+        set(SUFFIX "a")
     endif()
 
     set(BYPRODUCTS
diff --git a/cmake/BundledLibSSH2.cmake b/cmake/BundledLibSSH2.cmake
index b86da0c..7c3bf82 100644
--- a/cmake/BundledLibSSH2.cmake
+++ b/cmake/BundledLibSSH2.cmake
@@ -26,7 +26,9 @@ function(use_bundled_libssh2 SOURCE_DIR BINARY_DIR)
         set(BYPRODUCT "lib/libssh2.lib")
     else()
         include(GNUInstallDirs)
-        set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/libssh2.a")
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
+        set(BYPRODUCT "${LIBDIR}/libssh2.a")
     endif()
 
     # Set build options
diff --git a/cmake/BundledLibcURL.cmake b/cmake/BundledLibcURL.cmake
index 88f325e..6295ac9 100644
--- a/cmake/BundledLibcURL.cmake
+++ b/cmake/BundledLibcURL.cmake
@@ -26,7 +26,9 @@ function(use_bundled_curl SOURCE_DIR BINARY_DIR)
         set(BYPRODUCT "lib/libcurl.lib")
     else()
         include(GNUInstallDirs)
-        set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/libcurl.a")
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
+        set(BYPRODUCT "${LIBDIR}/libcurl.a")
     endif()
 
     # Set build options
diff --git a/cmake/BundledOpen62541.cmake b/cmake/BundledOpen62541.cmake
index c03c0bc..da1369a 100644
--- a/cmake/BundledOpen62541.cmake
+++ b/cmake/BundledOpen62541.cmake
@@ -24,7 +24,9 @@ function(use_bundled_open62541 SOURCE_DIR BINARY_DIR)
         set(BYPRODUCT "lib/open62541.lib")
     else()
         include(GNUInstallDirs)
-        set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/libopen62541.a")
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
+        set(BYPRODUCT "${LIBDIR}/libopen62541.a")
     endif()
 
     # Set build options
diff --git a/cmake/BundledOpenCV.cmake b/cmake/BundledOpenCV.cmake
index 1a48e89..b79fb98 100644
--- a/cmake/BundledOpenCV.cmake
+++ b/cmake/BundledOpenCV.cmake
@@ -17,9 +17,11 @@
 
 function(use_bundled_opencv SOURCE_DIR BINARY_DIR)
     if (WIN32)
-        set(CMAKE_INSTALL_LIBDIR "lib")
+        set(LIBDIR "lib")
     else()
         include(GNUInstallDirs)
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
     endif()
 
     # Define byproducts
@@ -37,21 +39,21 @@ function(use_bundled_opencv SOURCE_DIR BINARY_DIR)
 
     set(OPENCV_BYPRODUCT_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty/opencv-install")
     set(BYPRODUCTS
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_flann${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_dnn${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_objdetect${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_core${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_gapi${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_imgcodecs${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_calib3d${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_imgproc${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_photo${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_videoio${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_video${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_stitching${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_features2d${SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libjpeg-turbo${THIRDPARTY_SUFFIX}"
-        "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libpng${THIRDPARTY_SUFFIX}")
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_flann${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_dnn${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_objdetect${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_core${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_gapi${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_imgcodecs${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_calib3d${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_imgproc${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_photo${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_videoio${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_video${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_stitching${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_features2d${SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libjpeg-turbo${THIRDPARTY_SUFFIX}"
+        "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libpng${THIRDPARTY_SUFFIX}")
 
     # Set build options
     set(OPENCV_CMAKE_ARGS ${PASSTHROUGH_CMAKE_ARGS}
@@ -129,79 +131,79 @@ function(use_bundled_opencv SOURCE_DIR BINARY_DIR)
     file(MAKE_DIRECTORY ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libjpeg-turbo STATIC IMPORTED)
-    set_target_properties(OPENCV::libjpeg-turbo PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libjpeg-turbo${THIRDPARTY_SUFFIX}")
+    set_target_properties(OPENCV::libjpeg-turbo PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libjpeg-turbo${THIRDPARTY_SUFFIX}")
     add_dependencies(OPENCV::libjpeg-turbo opencv-external)
 
     add_library(OPENCV::libpng STATIC IMPORTED)
-    set_target_properties(OPENCV::libpng PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libpng${THIRDPARTY_SUFFIX}")
+    set_target_properties(OPENCV::libpng PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${THIRDPARTY_DIR}${PREFIX}libpng${THIRDPARTY_SUFFIX}")
     add_dependencies(OPENCV::libpng opencv-external)
 
     add_library(OPENCV::libopencv-core STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-core PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_core${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-core PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_core${SUFFIX}")
     add_dependencies(OPENCV::libopencv-core opencv-external ZLIB::ZLIB)
     target_include_directories(OPENCV::libopencv-core INTERFACE ${OPENCV_INCLUDE_DIR})
     target_link_libraries(OPENCV::libopencv-core INTERFACE ZLIB::ZLIB)
 
     add_library(OPENCV::libopencv-flann STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-flann PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_flann${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-flann PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_flann${SUFFIX}")
     add_dependencies(OPENCV::libopencv-flann opencv-external)
     target_include_directories(OPENCV::libopencv-flann INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-dnn STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-dnn PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_dnn${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-dnn PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_dnn${SUFFIX}")
     add_dependencies(OPENCV::libopencv-dnn opencv-external)
     target_include_directories(OPENCV::libopencv-dnn INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-objdetect STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-objdetect PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_objdetect${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-objdetect PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_objdetect${SUFFIX}")
     add_dependencies(OPENCV::libopencv-objdetect opencv-external)
     target_include_directories(OPENCV::libopencv-objdetect INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-gapi STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-gapi PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_gapi${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-gapi PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_gapi${SUFFIX}")
     add_dependencies(OPENCV::libopencv-gapi opencv-external)
     target_include_directories(OPENCV::libopencv-gapi INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-imgcodecs STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-imgcodecs PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_imgcodecs${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-imgcodecs PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_imgcodecs${SUFFIX}")
     add_dependencies(OPENCV::libopencv-imgcodecs opencv-external)
     target_include_directories(OPENCV::libopencv-imgcodecs INTERFACE ${OPENCV_INCLUDE_DIR})
     target_link_libraries(OPENCV::libopencv-imgcodecs INTERFACE OPENCV::libopencv-core OPENCV::libjpeg-turbo OPENCV::libpng)
 
     add_library(OPENCV::libopencv-calib3d STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-calib3d PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_calib3d${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-calib3d PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_calib3d${SUFFIX}")
     add_dependencies(OPENCV::libopencv-calib3d opencv-external)
     target_include_directories(OPENCV::libopencv-calib3d INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-imgproc STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-imgproc PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_imgproc${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-imgproc PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_imgproc${SUFFIX}")
     add_dependencies(OPENCV::libopencv-imgproc opencv-external)
     target_include_directories(OPENCV::libopencv-imgproc INTERFACE ${OPENCV_INCLUDE_DIR})
     target_link_libraries(OPENCV::libopencv-imgproc INTERFACE OPENCV::libopencv-core)
 
     add_library(OPENCV::libopencv-photo STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-photo PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_photo${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-photo PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_photo${SUFFIX}")
     add_dependencies(OPENCV::libopencv-photo opencv-external)
     target_include_directories(OPENCV::libopencv-photo INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-videoio STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-videoio PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_videoio${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-videoio PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_videoio${SUFFIX}")
     add_dependencies(OPENCV::libopencv-videoio opencv-external)
     target_include_directories(OPENCV::libopencv-videoio INTERFACE ${OPENCV_INCLUDE_DIR})
     target_link_libraries(OPENCV::libopencv-videoio INTERFACE OPENCV::libopencv-core)
 
     add_library(OPENCV::libopencv-video STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-video PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_video${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-video PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_video${SUFFIX}")
     add_dependencies(OPENCV::libopencv-video opencv-external)
     target_include_directories(OPENCV::libopencv-video INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-stitching STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-stitching PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_stitching${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-stitching PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_stitching${SUFFIX}")
     add_dependencies(OPENCV::libopencv-stitching opencv-external)
     target_include_directories(OPENCV::libopencv-stitching INTERFACE ${OPENCV_INCLUDE_DIR})
 
     add_library(OPENCV::libopencv-features2d STATIC IMPORTED)
-    set_target_properties(OPENCV::libopencv-features2d PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${CMAKE_INSTALL_LIBDIR}/${PREFIX}opencv_features2d${SUFFIX}")
+    set_target_properties(OPENCV::libopencv-features2d PROPERTIES IMPORTED_LOCATION "${OPENCV_BYPRODUCT_DIR}/${LIBDIR}/${PREFIX}opencv_features2d${SUFFIX}")
     add_dependencies(OPENCV::libopencv-features2d opencv-external)
     target_include_directories(OPENCV::libopencv-features2d INTERFACE ${OPENCV_INCLUDE_DIR})
 
diff --git a/cmake/BundledRocksDB.cmake b/cmake/BundledRocksDB.cmake
index de9c45d..76ce50a 100644
--- a/cmake/BundledRocksDB.cmake
+++ b/cmake/BundledRocksDB.cmake
@@ -23,7 +23,9 @@ function(use_bundled_rocksdb SOURCE_DIR BINARY_DIR)
         set(BYPRODUCT "lib/rocksdb.lib")
     else()
         include(GNUInstallDirs)
-        set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/librocksdb.a")
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
+        set(BYPRODUCT "${LIBDIR}/librocksdb.a")
     endif()
 
     # Set build options
diff --git a/cmake/BundledSpdlog.cmake b/cmake/BundledSpdlog.cmake
index b1d4bc7..974cbba 100644
--- a/cmake/BundledSpdlog.cmake
+++ b/cmake/BundledSpdlog.cmake
@@ -25,10 +25,12 @@ function(use_bundled_spdlog SOURCE_DIR BINARY_DIR)
         endif()
     else()
         include(GNUInstallDirs)
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
         if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
-            set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/libspdlogd.a")
+            set(BYPRODUCT "${LIBDIR}/libspdlogd.a")
         else()
-            set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/libspdlog.a")
+            set(BYPRODUCT "${LIBDIR}/libspdlog.a")
         endif()
     endif()
 
diff --git a/cmake/BundledYamlCpp.cmake b/cmake/BundledYamlCpp.cmake
index 5f4f2b3..d88663a 100644
--- a/cmake/BundledYamlCpp.cmake
+++ b/cmake/BundledYamlCpp.cmake
@@ -17,16 +17,18 @@
 
 function(use_bundled_yamlcpp SOURCE_DIR BINARY_DIR)
     if (WIN32)
-        set(CMAKE_INSTALL_LIBDIR "lib")
+        set(LIBDIR "lib")
     else()
         include(GNUInstallDirs)
+        string(REPLACE "/" ";" LIBDIR_LIST ${CMAKE_INSTALL_LIBDIR})
+        list(GET LIBDIR_LIST 0 LIBDIR)
     endif()
 
     # Define byproducts
     if (WIN32)
-        set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/yaml-cpp.lib")
+        set(BYPRODUCT "${LIBDIR}/yaml-cpp.lib")
     else()
-        set(BYPRODUCT "${CMAKE_INSTALL_LIBDIR}/libyaml-cpp.a")
+        set(BYPRODUCT "${LIBDIR}/libyaml-cpp.a")
     endif()
 
     # Set build options

[nifi-minifi-cpp] 01/05: MINIFICPP-1779 Verify multiple C2 commands in HB response

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adebreceni pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit bc46482985b5202479f83f47dc98e274cf434b6d
Author: Gabor Gyimesi <ga...@gmail.com>
AuthorDate: Fri Apr 1 12:51:22 2022 +0200

    MINIFICPP-1779 Verify multiple C2 commands in HB response
    
    Signed-off-by: Adam Debreceni <ad...@apache.org>
    
    This closes #1285
---
 .../http-curl/tests/C2MultipleCommandsTest.cpp     | 130 +++++++++++++++++++++
 extensions/http-curl/tests/CMakeLists.txt          |   1 +
 extensions/http-curl/tests/HTTPHandlers.h          |  63 ++++++----
 3 files changed, 174 insertions(+), 20 deletions(-)

diff --git a/extensions/http-curl/tests/C2MultipleCommandsTest.cpp b/extensions/http-curl/tests/C2MultipleCommandsTest.cpp
new file mode 100644
index 0000000..06697c3
--- /dev/null
+++ b/extensions/http-curl/tests/C2MultipleCommandsTest.cpp
@@ -0,0 +1,130 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef NDEBUG
+#include <string>
+#include <vector>
+#include <functional>
+
+#include "TestBase.h"
+#include "Catch.h"
+#include "HTTPIntegrationBase.h"
+#include "HTTPHandlers.h"
+
+class AckAuditor {
+ public:
+  void addAck(const std::string& ack) {
+    std::lock_guard<std::mutex> guard(acknowledged_operations_mutex_);
+    acknowledged_operations_.insert(ack);
+  }
+
+  bool isAcknowledged(const std::string& operation_id) const {
+    std::lock_guard<std::mutex> guard(acknowledged_operations_mutex_);
+    return acknowledged_operations_.count(operation_id) > 0;
+  }
+
+  void addVerifier(std::function<void(const rapidjson::Document&)> verifier) {
+    std::lock_guard<std::mutex> guard(verify_ack_mutex_);
+    ack_verifiers_.push_back(std::move(verifier));
+  }
+
+  void verifyAck(const rapidjson::Document& root) {
+    std::lock_guard<std::mutex> guard(verify_ack_mutex_);
+    if (ack_verifiers_.empty()) {
+      assert(false);
+    }
+
+    ack_verifiers_[next_verifier_index_](root);
+    ++next_verifier_index_;
+    if (next_verifier_index_ >= ack_verifiers_.size()) {
+      next_verifier_index_ = 0;
+    }
+  }
+
+ private:
+  mutable std::mutex acknowledged_operations_mutex_;
+  mutable std::mutex verify_ack_mutex_;
+  std::unordered_set<std::string> acknowledged_operations_;
+  std::vector<std::function<void(const rapidjson::Document&)>> ack_verifiers_;
+  uint32_t next_verifier_index_ = 0;
+};
+
+class MultipleC2CommandHandler: public HeartbeatHandler {
+ public:
+  explicit MultipleC2CommandHandler(AckAuditor& ack_auditor, std::shared_ptr<minifi::Configure> configuration)
+    : HeartbeatHandler(std::move(configuration)),
+      ack_auditor_(ack_auditor) {
+  }
+
+  void handleHeartbeat(const rapidjson::Document&, struct mg_connection * conn) override {
+    std::vector<C2Operation> operations{{"DESCRIBE", "manifest", "889345", {}}, {"DESCRIBE", "corecomponentstate", "889346", {}}};
+    ack_auditor_.addVerifier([this](const rapidjson::Document& root) {
+      verifyJsonHasAgentManifest(root);
+    });
+    ack_auditor_.addVerifier([](const rapidjson::Document& root) {
+      assert(root.HasMember("corecomponentstate"));
+    });
+    sendHeartbeatResponse(operations, conn);
+  }
+
+  void handleAcknowledge(const rapidjson::Document& root) override {
+    ack_auditor_.verifyAck(root);
+    if (root.IsObject() && root.HasMember("operationId")) {
+      ack_auditor_.addAck(root["operationId"].GetString());
+    }
+  }
+
+ private:
+  AckAuditor& ack_auditor_;
+};
+
+class VerifyC2MultipleCommands : public VerifyC2Base {
+ public:
+  explicit VerifyC2MultipleCommands(AckAuditor& auditor)
+    : ack_auditor_(auditor) {
+  }
+
+  void testSetup() override {
+    LogTestController::getInstance().setTrace<minifi::c2::C2Agent>();
+    LogTestController::getInstance().setDebug<minifi::c2::RESTSender>();
+    LogTestController::getInstance().setInfo<minifi::FlowController>();
+    VerifyC2Base::testSetup();
+  }
+
+  void configureFullHeartbeat() override {
+    configuration->set(org::apache::nifi::minifi::Configuration::nifi_c2_full_heartbeat, "false");
+  }
+
+  void runAssertions() override {
+    assert(utils::verifyEventHappenedInPollTime(3s, [&] {return ack_auditor_.isAcknowledged("889345");}));
+    assert(utils::verifyEventHappenedInPollTime(3s, [&] {return ack_auditor_.isAcknowledged("889346");}));
+  }
+
+ private:
+  AckAuditor& ack_auditor_;
+};
+
+int main(int argc, char **argv) {
+  const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat");
+  AckAuditor ack_auditor;
+  VerifyC2MultipleCommands harness(ack_auditor);
+  harness.setKeyDir(args.key_dir);
+  MultipleC2CommandHandler responder(ack_auditor, harness.getConfiguration());
+  harness.setUrl(args.url, &responder);
+  harness.run(args.test_file);
+}
diff --git a/extensions/http-curl/tests/CMakeLists.txt b/extensions/http-curl/tests/CMakeLists.txt
index 0077008..975b6e9 100644
--- a/extensions/http-curl/tests/CMakeLists.txt
+++ b/extensions/http-curl/tests/CMakeLists.txt
@@ -101,3 +101,4 @@ add_test(NAME C2LogHeartbeatTest COMMAND C2LogHeartbeatTest)
 add_test(NAME C2DebugBundleTest COMMAND C2DebugBundleTest)
 add_test(NAME C2PropertiesUpdateTests COMMAND C2PropertiesUpdateTests)
 add_test(NAME C2ClearCoreComponentStateTest COMMAND C2ClearCoreComponentStateTest "${TEST_RESOURCES}/TestC2DescribeCoreComponentState.yml"  "${TEST_RESOURCES}/")
+add_test(NAME C2MultipleCommandsTest COMMAND C2MultipleCommandsTest "${TEST_RESOURCES}/TestC2DescribeCoreComponentState.yml"  "${TEST_RESOURCES}/")
diff --git a/extensions/http-curl/tests/HTTPHandlers.h b/extensions/http-curl/tests/HTTPHandlers.h
index c5b6c2e..a0acc6b 100644
--- a/extensions/http-curl/tests/HTTPHandlers.h
+++ b/extensions/http-curl/tests/HTTPHandlers.h
@@ -404,31 +404,54 @@ class HeartbeatHandler : public ServerAwareHandler {
   }
 
  protected:
-  void sendHeartbeatResponse(const std::string& operation, const std::string& operand, const std::string& operationId, struct mg_connection * conn,
+  struct C2Operation {
+    std::string operation;
+    std::string operand;
+    std::string operation_id;
+    std::unordered_map<std::string, std::string> args;
+  };
+
+  void sendHeartbeatResponse(const std::string& operation, const std::string& operand, const std::string& operation_id, struct mg_connection* conn,
       const std::unordered_map<std::string, std::string>& args = {}) {
-    std::string resp_args;
-    if (!args.empty()) {
-      resp_args = ", \"args\": {";
-      auto it = args.begin();
-      while (it != args.end()) {
-        resp_args += "\"" + it->first + "\": \"" + it->second + "\"";
-        ++it;
-        if (it != args.end()) {
-          resp_args += ", ";
+    sendHeartbeatResponse({{operation, operand, operation_id, args}}, conn);
+  }
+
+  void sendHeartbeatResponse(const std::vector<C2Operation>& operations, struct mg_connection * conn) {
+    std::string operation_jsons;
+    for (const auto& c2_operation : operations) {
+      std::string resp_args;
+      if (!c2_operation.args.empty()) {
+        resp_args = ", \"args\": {";
+        auto it = c2_operation.args.begin();
+        while (it != c2_operation.args.end()) {
+          resp_args += "\"" + it->first + "\": \"" + it->second + "\"";
+          ++it;
+          if (it != c2_operation.args.end()) {
+            resp_args += ", ";
+          }
         }
+        resp_args += "}";
+      }
+
+      std::string operation_json = "{"
+        "\"operation\" : \"" + c2_operation.operation + "\","
+        "\"operationid\" : \"" + c2_operation.operation_id + "\","
+        "\"operand\": \"" + c2_operation.operand + "\"" +
+        resp_args + "}";
+
+      if (operation_jsons.empty()) {
+        operation_jsons += operation_json;
+      } else {
+        operation_jsons += ", " + operation_json;
       }
-      resp_args += "}";
     }
-    std::string heartbeat_response = "{\"operation\" : \"heartbeat\",\"requested_operations\": [  {"
-          "\"operation\" : \"" + operation + "\","
-          "\"operationid\" : \"" + operationId + "\","
-          "\"operand\": \"" + operand + "\"" +
-          resp_args + "}]}";
 
-      mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: "
-                "text/plain\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n",
-                heartbeat_response.length());
-      mg_printf(conn, "%s", heartbeat_response.c_str());
+    std::string heartbeat_response = "{\"operation\" : \"heartbeat\",\"requested_operations\": [ " + operation_jsons + " ]}";
+
+    mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: "
+              "text/plain\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n",
+              heartbeat_response.length());
+    mg_printf(conn, "%s", heartbeat_response.c_str());
   }
 
   void verifyJsonHasAgentManifest(const rapidjson::Document& root, const std::vector<std::string>& verify_components = {}, const std::vector<std::string>& disallowed_properties = {}) {

[nifi-minifi-cpp] 02/05: MINIFICPP-1783 Encrypted values in agent manifest should remain in encrypted form

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adebreceni pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit aa654309676a3a063706c70b3b5d369d90ab31db
Author: Gabor Gyimesi <ga...@gmail.com>
AuthorDate: Fri Apr 1 12:53:10 2022 +0200

    MINIFICPP-1783 Encrypted values in agent manifest should remain in encrypted form
    
    Signed-off-by: Adam Debreceni <ad...@apache.org>
    
    This closes #1289
---
 extensions/http-curl/tests/C2DescribeManifestTest.cpp | 10 ++++++++++
 extensions/http-curl/tests/HTTPHandlers.h             |  2 +-
 libminifi/src/FlowController.cpp                      |  2 +-
 libminifi/src/c2/C2Client.cpp                         |  2 +-
 libminifi/test/integration/IntegrationBase.h          |  4 ++++
 5 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/extensions/http-curl/tests/C2DescribeManifestTest.cpp b/extensions/http-curl/tests/C2DescribeManifestTest.cpp
index 5c46f5c..a6a9a38 100644
--- a/extensions/http-curl/tests/C2DescribeManifestTest.cpp
+++ b/extensions/http-curl/tests/C2DescribeManifestTest.cpp
@@ -22,6 +22,7 @@
 #include "Catch.h"
 #include "HTTPIntegrationBase.h"
 #include "HTTPHandlers.h"
+#include "properties/Configuration.h"
 
 class DescribeManifestHandler: public HeartbeatHandler {
  public:
@@ -41,8 +42,17 @@ class DescribeManifestHandler: public HeartbeatHandler {
 int main(int argc, char **argv) {
   const cmd_args args = parse_cmdline_args(argc, argv, "heartbeat");
   VerifyC2Describe harness;
+  utils::crypto::Bytes encryption_key = utils::StringUtils::from_hex("4024b327fdc987ce3eb43dd1f690b9987e4072e0020e3edf4349ce1ad91a4e38");
+  minifi::Decryptor decryptor{utils::crypto::EncryptionProvider{encryption_key}};
+  std::string encrypted_value = "l3WY1V27knTiPa6jVX0jrq4qjmKsySOu||ErntqZpHP1M+6OkA14p5sdnqJhuNHWHDVUU5EyMloTtSytKk9a5xNKo=";
+
+  harness.setConfiguration(std::make_shared<minifi::Configure>(decryptor));
   harness.setKeyDir(args.key_dir);
   DescribeManifestHandler responder(harness.getConfiguration());
+
+  harness.getConfiguration()->set(minifi::Configuration::nifi_rest_api_password, encrypted_value);
+  harness.getConfiguration()->set(std::string(minifi::Configuration::nifi_rest_api_password) + ".protected", utils::crypto::EncryptionType::name());
+
   harness.setUrl(args.url, &responder);
   harness.run(args.test_file);
 }
diff --git a/extensions/http-curl/tests/HTTPHandlers.h b/extensions/http-curl/tests/HTTPHandlers.h
index a0acc6b..c136ab1 100644
--- a/extensions/http-curl/tests/HTTPHandlers.h
+++ b/extensions/http-curl/tests/HTTPHandlers.h
@@ -556,7 +556,7 @@ class HeartbeatHandler : public ServerAwareHandler {
           std::unordered_map<std::string, std::string> config_property;
           if (ranges::find(disallowed_properties, property.name) == ranges::end(disallowed_properties)) {
             config_property.emplace("propertyName", property.name);
-            if (auto value = configuration_->get(std::string(property.name))) {
+            if (auto value = configuration_->getString(std::string(property.name))) {
               config_property.emplace("propertyValue", *value);
             }
             config_property.emplace("validator", property.validator->getName());
diff --git a/libminifi/src/FlowController.cpp b/libminifi/src/FlowController.cpp
index f518572..b6fe4cc 100644
--- a/libminifi/src/FlowController.cpp
+++ b/libminifi/src/FlowController.cpp
@@ -431,7 +431,7 @@ std::shared_ptr<state::response::ResponseNode> FlowController::getAgentManifest(
   agentInfo->setUpdatePolicyController(std::static_pointer_cast<controllers::UpdatePolicyControllerService>(getControllerService(c2::C2Agent::UPDATE_NAME)).get());
   agentInfo->setAgentIdentificationProvider(configuration_);
   agentInfo->setConfigurationReader([this](const std::string& key){
-    return configuration_->get(key);
+    return configuration_->getString(key);
   });
   agentInfo->includeAgentStatus(false);
   return agentInfo;
diff --git a/libminifi/src/c2/C2Client.cpp b/libminifi/src/c2/C2Client.cpp
index 3a195ef..f6f067e 100644
--- a/libminifi/src/c2/C2Client.cpp
+++ b/libminifi/src/c2/C2Client.cpp
@@ -111,7 +111,7 @@ void C2Client::initialize(core::controller::ControllerServiceProvider *controlle
       }
       if (agent_node != nullptr) {
         agent_node->setConfigurationReader([this](const std::string& key){
-          return configuration_->get(key);
+          return configuration_->getString(key);
         });
       }
       auto configuration_checksums = dynamic_cast<state::response::ConfigurationChecksums*>(response_node.get());
diff --git a/libminifi/test/integration/IntegrationBase.h b/libminifi/test/integration/IntegrationBase.h
index db64e13..d247bd4 100644
--- a/libminifi/test/integration/IntegrationBase.h
+++ b/libminifi/test/integration/IntegrationBase.h
@@ -61,6 +61,10 @@ class IntegrationBase {
     return configuration;
   }
 
+  void setConfiguration(std::shared_ptr<minifi::Configure> configuration) {
+    this->configuration = std::move(configuration);
+  }
+
   virtual void cleanup() {
     if (!state_dir.empty()) {
       utils::file::delete_dir(state_dir);

[nifi-minifi-cpp] 03/05: MINIFICPP-1789 - Log checking is wrong in integration tests

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adebreceni pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 163c7c27efab153f26be5b54cbeb67ee6daadca4
Author: Adam Markovics <nu...@gmail.com>
AuthorDate: Fri Apr 1 12:54:22 2022 +0200

    MINIFICPP-1789 - Log checking is wrong in integration tests
    
    Signed-off-by: Adam Debreceni <ad...@apache.org>
    
    This closes #1290
---
 docker/test/integration/MiNiFi_integration_test_driver.py | 4 ++--
 docker/test/integration/features/mqtt.feature             | 6 +++---
 docker/test/integration/steps/steps.py                    | 4 ++--
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/docker/test/integration/MiNiFi_integration_test_driver.py b/docker/test/integration/MiNiFi_integration_test_driver.py
index 138e4fe..91a39e8 100644
--- a/docker/test/integration/MiNiFi_integration_test_driver.py
+++ b/docker/test/integration/MiNiFi_integration_test_driver.py
@@ -247,8 +247,8 @@ class MiNiFi_integration_test():
     def check_query_results(self, postgresql_container_name, query, number_of_rows, timeout_seconds):
         assert self.cluster.check_query_results(postgresql_container_name, query, number_of_rows, timeout_seconds)
 
-    def wait_for_container_logs(self, container_name, log_pattern, timeout_seconds, count=1):
-        self.cluster.wait_for_app_logs_regex(container_name, log_pattern, timeout_seconds, count)
+    def check_container_log_matches_regex(self, container_name, log_pattern, timeout_seconds, count=1):
+        assert self.cluster.wait_for_app_logs_regex(container_name, log_pattern, timeout_seconds, count)
 
     def add_test_blob(self, blob_name, content, with_snapshot):
         self.cluster.add_test_blob(blob_name, content, with_snapshot)
diff --git a/docker/test/integration/features/mqtt.feature b/docker/test/integration/features/mqtt.feature
index 784e7ac..bcdcaec 100644
--- a/docker/test/integration/features/mqtt.feature
+++ b/docker/test/integration/features/mqtt.feature
@@ -33,7 +33,7 @@ Feature: Sending data to MQTT streaming platform using PublishMQTT
 
     When both instances start up
     Then a flowfile with the content "test" is placed in the monitored directory in less than 60 seconds
-    And the MQTT broker has a log line matching "Received PUBLISH from .*testtopic.*\\(4 bytes\\)"
+    And the MQTT broker has a log line matching "Received PUBLISH from .*testtopic.*\(4 bytes\)"
 
   Scenario: If the MQTT broker does not exist, then no flow files are processed
     Given a GetFile processor with the "Input Directory" property set to "/tmp/input"
@@ -60,7 +60,7 @@ Feature: Sending data to MQTT streaming platform using PublishMQTT
 
     And an MQTT broker is deployed in correspondence with the PublishMQTT
     And a flowfile with the content "test" is placed in the monitored directory in less than 60 seconds
-    And the MQTT broker has a log line matching "Received PUBLISH from .*testtopic.*\\(4 bytes\\)"
+    And the MQTT broker has a log line matching "Received PUBLISH from .*testtopic.*\(4 bytes\)"
 
   Scenario: A MiNiFi instance publishes and consumes data to/from an MQTT broker
     Given a GetFile processor with the "Input Directory" property set to "/tmp/input"
@@ -77,5 +77,5 @@ Feature: Sending data to MQTT streaming platform using PublishMQTT
 
     When both instances start up
     Then a flowfile with the content "test" is placed in the monitored directory in less than 60 seconds
-    And the MQTT broker has a log line matching "Received PUBLISH from .*testtopic.*\\(4 bytes\\)"
+    And the MQTT broker has a log line matching "Received PUBLISH from .*testtopic.*\(4 bytes\)"
     And the MQTT broker has a log line matching "Received SUBSCRIBE from"
diff --git a/docker/test/integration/steps/steps.py b/docker/test/integration/steps/steps.py
index ac00506..8f1b614 100644
--- a/docker/test/integration/steps/steps.py
+++ b/docker/test/integration/steps/steps.py
@@ -744,12 +744,12 @@ def step_impl(context, log_message, duration):
 # MQTT
 @then("the MQTT broker has a log line matching \"{log_pattern}\"")
 def step_impl(context, log_pattern):
-    context.test.wait_for_container_logs('mqtt-broker', log_pattern, 30, count=1)
+    context.test.check_container_log_matches_regex('mqtt-broker', log_pattern, 30, count=1)
 
 
 @then("the \"{minifi_container_name}\" flow has a log line matching \"{log_pattern}\" in less than {duration}")
 def step_impl(context, minifi_container_name, log_pattern, duration):
-    context.test.wait_for_container_logs(minifi_container_name, log_pattern, timeparse(duration), count=1)
+    context.test.check_container_log_matches_regex(minifi_container_name, log_pattern, timeparse(duration), count=1)
 
 
 @then("an MQTT broker is deployed in correspondence with the PublishMQTT")

[nifi-minifi-cpp] 05/05: MINIFICPP-1788 flush old bins on expiration

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adebreceni pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit 47000876a2cdcdb6d055527ceca4b337769c2e68
Author: Marton Szasz <sz...@apache.org>
AuthorDate: Fri Apr 1 12:57:02 2022 +0200

    MINIFICPP-1788 flush old bins on expiration
    
    Before this change, if there were old flow files in
    MergeContent/BinFiles, they were stuck until there was another incoming
    flow file to the processor, because the processor was not triggered,
    regardless of scheduling strategy.
    
    Now the processor is always triggered, regardless of incoming flow
    files, so it can check and flush expired bins. This didn't result in a
    noticably increased CPU usage even with EVENT_TRIGGERED scheduling
    strategy on my system.
    
    Signed-off-by: Adam Debreceni <ad...@apache.org>
    
    This closes #1293
---
 extensions/libarchive/BinFiles.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/extensions/libarchive/BinFiles.cpp b/extensions/libarchive/BinFiles.cpp
index e8d6e64..9ba49e4 100644
--- a/extensions/libarchive/BinFiles.cpp
+++ b/extensions/libarchive/BinFiles.cpp
@@ -119,6 +119,8 @@ void BinFiles::onSchedule(core::ProcessContext *context, core::ProcessSessionFac
     logger_->log_debug("BinFiles: MaxBinCount [%" PRIu32 "]", maxBinCount_);
   }
   if (auto max_bin_age = context->getProperty<core::TimePeriodValue>(MaxBinAge)) {
+    // We need to trigger the processor even when there are no incoming flow files so that it can flush the bins.
+    setTriggerWhenEmpty(true);
     this->binManager_.setBinAge(max_bin_age->getMilliseconds());
     logger_->log_debug("BinFiles: MaxBinAge [%" PRId64 "] ms", int64_t{max_bin_age->getMilliseconds().count()});
   }