diff --git a/bootstrap/cli.py b/bootstrap/cli.py index de3e30124e..c4b70bc1ef 100644 --- a/bootstrap/cli.py +++ b/bootstrap/cli.py @@ -63,7 +63,7 @@ def run_conan_install(minifi_options: MinifiOptions, package_manager: PackageMan return True conan_options = add_conan_options_from_cmake_options(["ENABLE_ALL", "ENABLE_LIBARCHIVE", "ENABLE_ROCKSDB", "ENABLE_SFTP", "ENABLE_PROMETHEUS", "ENABLE_BZIP2", "ENABLE_LZMA", "ENABLE_MQTT", "ENABLE_COUCHBASE", "ENABLE_KAFKA", "ENABLE_OPC", "ENABLE_GCP", "ENABLE_GRPC_FOR_LOKI", "ENABLE_BUSTACHE", "ENABLE_KUBERNETES", - "ENABLE_AZURE", "ENABLE_LLAMACPP", "ENABLE_AWS", "PORTABLE", "SKIP_TESTS"], + "ENABLE_AZURE", "ENABLE_LLAMACPP", "ENABLE_AWS", "ENABLE_SQL", "PORTABLE", "SKIP_TESTS"], minifi_options) if minifi_options.custom_malloc is not None and minifi_options.custom_malloc.value not in (None, "OFF"): conan_options += f' -o "&:custom_malloc={minifi_options.custom_malloc.value}"' diff --git a/cmake/BundledIodbc.cmake b/cmake/BundledIodbc.cmake new file mode 100644 index 0000000000..f90bab01bf --- /dev/null +++ b/cmake/BundledIodbc.cmake @@ -0,0 +1,56 @@ +# 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. + +# Define byproducts +set(IODBC_BYPRODUCT "lib/libiodbc.a") + +set(IODBC_BYPRODUCT_DIR "${CMAKE_BINARY_DIR}/thirdparty/iodbc-install/") + +set(IODBC_PC "${Patch_EXECUTABLE}" -p1 -i "${CMAKE_SOURCE_DIR}/thirdparty/iodbc/all/patches/GCC-15-needs-typedef-SQLRETURN-HPROC.patch") +# Build project +ExternalProject_Add( + iodbc-external + URL "https://github.com/openlink/iODBC/archive/v3.52.16.tar.gz" + URL_HASH "SHA256=a0cf0375b462f98c0081c2ceae5ef78276003e57cdf1eb86bd04508fb62a0660" + BUILD_IN_SOURCE true + SOURCE_DIR "${CMAKE_BINARY_DIR}/thirdparty/iodbc-src" + PATCH_COMMAND "${IODBC_PC}" + BUILD_COMMAND make + CMAKE_COMMAND "" + UPDATE_COMMAND "" + INSTALL_COMMAND make install + CONFIGURE_COMMAND bash "-c" "./autogen.sh && ./configure --prefix=${IODBC_BYPRODUCT_DIR} --with-pic CFLAGS='${CMAKE_C_FLAGS} -std=gnu17'" + STEP_TARGETS build + BUILD_BYPRODUCTS "${IODBC_BYPRODUCT_DIR}/${IODBC_BYPRODUCT}" + EXCLUDE_FROM_ALL TRUE +) + +# Set variables +set(IODBC_FOUND "YES" CACHE STRING "" FORCE) +set(IODBC_INCLUDE_DIRS "${IODBC_BYPRODUCT_DIR}/include" CACHE STRING "" FORCE) +set(IODBC_LIBRARIES "${IODBC_BYPRODUCT_DIR}/${IODBC_BYPRODUCT}" CACHE STRING "" FORCE) + +# Set exported variables for FindPackage.cmake +set(EXPORTED_IODBC_INCLUDE_DIRS "${IODBC_INCLUDE_DIRS}" CACHE STRING "" FORCE) +set(EXPORTED_IODBC_LIBRARIES "${IODBC_LIBRARIES}" CACHE STRING "" FORCE) + +# Create imported targets +add_library(ODBC::ODBC STATIC IMPORTED) +set_target_properties(ODBC::ODBC PROPERTIES IMPORTED_LOCATION "${IODBC_LIBRARIES}") +add_dependencies(ODBC::ODBC iodbc-external) +file(MAKE_DIRECTORY ${IODBC_INCLUDE_DIRS}) +set_property(TARGET ODBC::ODBC APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${IODBC_INCLUDE_DIRS}) diff --git a/cmake/GetIODBC.cmake b/cmake/GetIODBC.cmake new file mode 100644 index 0000000000..0fefa8e805 --- /dev/null +++ b/cmake/GetIODBC.cmake @@ -0,0 +1,24 @@ +# 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. + +if(MINIFI_IODBC_SOURCE STREQUAL "CONAN") + message("Using Conan to install iODBC") + find_package(ODBC REQUIRED) +elseif(MINIFI_IODBC_SOURCE STREQUAL "BUILD") + message("Using CMake to build iODBC from source") + include(BundledIodbc) +endif() diff --git a/cmake/GetSOCI.cmake b/cmake/GetSOCI.cmake new file mode 100644 index 0000000000..1d4e289cf6 --- /dev/null +++ b/cmake/GetSOCI.cmake @@ -0,0 +1,28 @@ +# 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. + +if(MINIFI_SOCI_SOURCE STREQUAL "CONAN") + message("Using Conan to install SOCI") + find_package(SOCI REQUIRED) + if(NOT TARGET SOCI::SOCI) + add_library(SOCI::SOCI INTERFACE IMPORTED) + target_link_libraries(SOCI::SOCI INTERFACE SOCI::soci_core_static SOCI::soci_odbc_static) + endif() +elseif(MINIFI_SOCI_SOURCE STREQUAL "BUILD") + message("Using CMake to build SOCI from source") + include(Soci) +endif() diff --git a/cmake/MiNiFiOptions.cmake b/cmake/MiNiFiOptions.cmake index eaa740e1b1..a8d1d53737 100644 --- a/cmake/MiNiFiOptions.cmake +++ b/cmake/MiNiFiOptions.cmake @@ -192,6 +192,8 @@ add_minifi_multi_option(MINIFI_LLAMACPP_SOURCE "Retrieves llama.cpp from provide add_minifi_multi_option(MINIFI_DATE_SOURCE "Retrieves date from provided source" "BUILD;CONAN" "${MINIFI_DEFAULT_DEPENDENCY_SOURCE}") add_minifi_multi_option(MINIFI_WINFLEXBISON_SOURCE "Retrieves winflexbison from provided source" "BUILD;CONAN" "${MINIFI_DEFAULT_DEPENDENCY_SOURCE}") add_minifi_multi_option(MINIFI_AWS_SDK_CPP_SOURCE "Retrieves AWS SDK for C++ from provided source" "BUILD;CONAN" "${MINIFI_DEFAULT_DEPENDENCY_SOURCE}") +add_minifi_multi_option(MINIFI_IODBC_SOURCE "Retrieves iODBC from provided source" "BUILD;CONAN" "${MINIFI_DEFAULT_DEPENDENCY_SOURCE}") +add_minifi_multi_option(MINIFI_SOCI_SOURCE "Retrieves SOCI from provided source" "BUILD;CONAN" "${MINIFI_DEFAULT_DEPENDENCY_SOURCE}") # Docker options diff --git a/cmake/Soci.cmake b/cmake/Soci.cmake new file mode 100644 index 0000000000..16cd6a5a25 --- /dev/null +++ b/cmake/Soci.cmake @@ -0,0 +1,47 @@ +# 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. + +include(FetchContent) + +include(fmt) + +set(PATCH_FILE1 "${CMAKE_SOURCE_DIR}/thirdparty/soci/all/patches/disable-sqlwchar-support.patch") +set(PATCH_FILE2 "${CMAKE_SOURCE_DIR}/thirdparty/soci/all/patches/odbc-get-parameter-name-bounds-safe.patch") +set(PC ${Bash_EXECUTABLE} -c "set -x &&\ + (\\\"${Patch_EXECUTABLE}\\\" -p1 -R -s -f --dry-run -i \\\"${PATCH_FILE1}\\\" || \\\"${Patch_EXECUTABLE}\\\" -p1 -N -i \\\"${PATCH_FILE1}\\\") &&\ + (\\\"${Patch_EXECUTABLE}\\\" -p1 -R -s -f --dry-run -i \\\"${PATCH_FILE2}\\\" || \\\"${Patch_EXECUTABLE}\\\" -p1 -N -i \\\"${PATCH_FILE2}\\\")") + +set(SOCI_TESTS OFF CACHE BOOL "" FORCE) +set(SOCI_SHARED OFF CACHE BOOL "" FORCE) +set(SOCI_ODBC ON CACHE BOOL "" FORCE) +set(SOCI_SQLITE3 OFF CACHE BOOL "" FORCE) +set(SOCI_LTO OFF CACHE BOOL "" FORCE) +set(WITH_BOOST OFF CACHE BOOL "" FORCE) + +FetchContent_Declare( + soci + URL "https://github.com/SOCI/soci/archive/refs/tags/v4.1.4.tar.gz" + URL_HASH "SHA256=144f017cccc2e2d806badb3313d6ab3c67a1925bccaa747a46fb3907108a615d" + PATCH_COMMAND "${PC}" + SYSTEM +) + +FetchContent_MakeAvailable(soci) + +if(NOT WIN32) + add_dependencies(soci_core ODBC::ODBC) +endif() diff --git a/conanfile.py b/conanfile.py index e6052d5693..f4f0f69ac2 100644 --- a/conanfile.py +++ b/conanfile.py @@ -42,12 +42,12 @@ class MiNiFiCppMain(ConanFile): "enable_rocksdb": [True, False], "enable_sftp": [True, False], "enable_prometheus": [True, False], "enable_bzip2": [True, False], "enable_lzma": [True, False], "enable_mqtt": [True, False], "enable_couchbase": [True, False], "enable_kafka": [True, False], "enable_opc": [True, False], "enable_gcp": [True, False], "enable_grpc_for_loki": [True, False], "enable_bustache": [True, False], "enable_kubernetes": [True, False], "enable_azure": [True, False], "enable_llamacpp": [True, False], - "enable_aws": [True, False], "skip_tests": [True, False], "portable": [True, False]} + "enable_aws": [True, False], "enable_sql": [True, False], "skip_tests": [True, False], "portable": [True, False]} default_options = {"shared": False, "fPIC": True, "custom_malloc": False, "enable_all": False, "enable_libarchive": False, "enable_rocksdb": False, "enable_sftp": False, "enable_prometheus": False, "enable_bzip2": False, "enable_lzma": False, "enable_mqtt": False, "enable_couchbase": False, "enable_kafka": False, "enable_opc": False, "enable_gcp": False, "enable_grpc_for_loki": False, "enable_bustache": False, "enable_kubernetes": False, "enable_azure": False, "enable_llamacpp": False, "enable_aws": False, - "skip_tests": False, "portable": True} + "enable_sql": False, "skip_tests": False, "portable": True} exports_sources = shared_sources @@ -104,6 +104,8 @@ def requirements(self): self.requires("llama-cpp/b8944@minifi/develop") if self.options.enable_all or self.options.enable_aws: self.requires("aws-sdk-cpp/1.11.807@minifi/develop") + if self.options.enable_all or self.options.enable_sql: + self.requires("soci/4.1.4@minifi/develop") if self.options.custom_malloc == "jemalloc": self.requires("jemalloc/5.3.1") @@ -132,17 +134,20 @@ def configure(self): self.options["librdkafka"].sasl = False self.options["librdkafka"].zstd = True self.options["librdkafka"].zlib = True - if (self.options.enable_all or self.options.get_safe("enable_gcp")) and not self.options.skip_tests: + if (self.options.enable_all or self.options.enable_gcp) and not self.options.skip_tests: self.options["google-cloud-cpp"].with_mocks = True - if self.options.enable_all or self.options.get_safe("enable_aws"): + if self.options.enable_all or self.options.enable_aws: self.options["aws-sdk-cpp"].s3 = True self.options["aws-sdk-cpp"].kinesis = True setattr(self.options["aws-sdk-cpp"], "s3-crt", True) setattr(self.options["aws-sdk-cpp"], "text-to-speech", False) - if self.options.enable_all or self.options.get_safe("enable_llamacpp"): + if self.options.enable_all or self.options.enable_llamacpp: self.options["llama-cpp"].portable = self.options.portable - if self.options.enable_all or self.options.get_safe("enable_mqtt"): + if self.options.enable_all or self.options.enable_mqtt: self.options["paho-mqtt-c"].high_performance = True + if self.options.enable_all or self.options.enable_sql: + self.options["soci"].shared = False + self.options["soci"].with_odbc = True def generate(self): tc = CMakeToolchain(self) diff --git a/extensions/sql/CMakeLists.txt b/extensions/sql/CMakeLists.txt index 849426f126..bbb6aee0e1 100644 --- a/extensions/sql/CMakeLists.txt +++ b/extensions/sql/CMakeLists.txt @@ -21,160 +21,24 @@ if (NOT (ENABLE_ALL OR ENABLE_SQL)) return() endif() -include(${CMAKE_SOURCE_DIR}/extensions/ExtensionHeader.txt) - -include_directories(SYSTEM ../../thirdparty/rapidjson-1.1.0/include/ ../../thirdparty/rapidjson-1.1.0/include/rapidjson) -include_directories(".") - -file(GLOB SOURCES "*.cpp" "services/*.cpp" "processors/*.cpp" "data/*.cpp") - -add_minifi_library(minifi-sql SHARED ${SOURCES}) - if(WIN32) find_package(ODBC REQUIRED) else() - # Build iODBC - - # Define byproducts - set(IODBC_BYPRODUCT "lib/libiodbc.a") - - set(IODBC_BYPRODUCT_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty/iodbc-install/") - - set(IODBC_PC "${Patch_EXECUTABLE}" -p1 -i "${CMAKE_SOURCE_DIR}/thirdparty/iODBC/GCC-15-needs-typedef-SQLRETURN-HPROC.patch") - # Build project - ExternalProject_Add( - iodbc-external - URL "https://github.com/openlink/iODBC/archive/v3.52.16.tar.gz" - URL_HASH "SHA256=a0cf0375b462f98c0081c2ceae5ef78276003e57cdf1eb86bd04508fb62a0660" - BUILD_IN_SOURCE true - SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty/iodbc-src" - PATCH_COMMAND "${IODBC_PC}" - BUILD_COMMAND make - CMAKE_COMMAND "" - UPDATE_COMMAND "" - INSTALL_COMMAND make install - CONFIGURE_COMMAND bash "-c" "./autogen.sh && ./configure --prefix=${IODBC_BYPRODUCT_DIR} --with-pic CFLAGS='${CMAKE_C_FLAGS} -std=gnu17'" - STEP_TARGETS build - BUILD_BYPRODUCTS "${IODBC_BYPRODUCT_DIR}/${IODBC_BYPRODUCT}" - EXCLUDE_FROM_ALL TRUE - ) - - # Set variables - set(IODBC_FOUND "YES" CACHE STRING "" FORCE) - set(IODBC_INCLUDE_DIRS "${IODBC_BYPRODUCT_DIR}/include" CACHE STRING "" FORCE) - set(IODBC_LIBRARIES "${IODBC_BYPRODUCT_DIR}/${IODBC_BYPRODUCT}" CACHE STRING "" FORCE) - - # Set exported variables for FindPackage.cmake - set(EXPORTED_IODBC_INCLUDE_DIRS "${IODBC_INCLUDE_DIRS}" CACHE STRING "" FORCE) - set(EXPORTED_IODBC_LIBRARIES "${IODBC_LIBRARIES}" CACHE STRING "" FORCE) - - # Create imported targets - add_library(ODBC::ODBC STATIC IMPORTED) - set_target_properties(ODBC::ODBC PROPERTIES IMPORTED_LOCATION "${IODBC_LIBRARIES}") - add_dependencies(ODBC::ODBC iodbc-external) - file(MAKE_DIRECTORY ${IODBC_INCLUDE_DIRS}) - set_property(TARGET ODBC::ODBC APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${IODBC_INCLUDE_DIRS}) + include(GetIODBC) endif() -# Build SOCI +include(GetSOCI) -# Define byproducts -# This should be based on GNUInstallDirs, but it's done wrong in Soci: -# https://github.com/SOCI/soci/blob/release/4.0/CMakeLists.txt#L140 -if(APPLE OR CMAKE_SIZEOF_VOID_P EQUAL 4) - set(LIBDIR "lib") -else() - set(LIBDIR "lib64") -endif() - -if (WIN32) - set(BYPRODUCT_SUFFIX "_4_0.lib") -else() - set(BYPRODUCT_SUFFIX ".a") -endif() - -set(SOCI_BYPRODUCTS - "${LIBDIR}/libsoci_core${BYPRODUCT_SUFFIX}" - "${LIBDIR}/libsoci_odbc${BYPRODUCT_SUFFIX}" - ) - -set(SOCI_BYPRODUCT_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty/soci-install") - -foreach(SOCI_BYPRODUCT ${SOCI_BYPRODUCTS}) - list(APPEND SOCI_LIBRARIES_LIST "${SOCI_BYPRODUCT_DIR}/${SOCI_BYPRODUCT}") -endforeach(SOCI_BYPRODUCT) - -if(WIN32) - # Set build options - set(SOCI_CMAKE_ARGS ${PASSTHROUGH_CMAKE_ARGS} - "-DCMAKE_INSTALL_PREFIX=${SOCI_BYPRODUCT_DIR}" - "-DSOCI_TESTS=OFF" - "-DSOCI_SHARED=OFF" - "-DSOCI_CXX_C11=ON" - "-DWITH_ODBC=ON" - "-DWITH_BOOST=OFF") -else() - # SOCI has its own FindODBC.cmake file - # Set build options - set(SOCI_CMAKE_ARGS ${PASSTHROUGH_CMAKE_ARGS} - "-DCMAKE_INSTALL_PREFIX=${SOCI_BYPRODUCT_DIR}" - "-DSOCI_TESTS=OFF" - "-DSOCI_SHARED=OFF" - "-DSOCI_CXX_C11=ON" - "-DSOCI_ODBC=ON" - "-DODBC_INCLUDE_DIR=${IODBC_INCLUDE_DIRS}" - "-DODBC_LIBRARY=${IODBC_LIBRARIES}" - "-DWITH_BOOST=OFF") -endif() - -if(NOT WIN32) - list(APPEND SOCI_CMAKE_ARGS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake/" - "-DEXPORTED_IODBC_INCLUDE_DIRS=${EXPORTED_IODBC_INCLUDE_DIRS}" - "-DEXPORTED_IODBC_LIBRARIES=${EXPORTED_IODBC_LIBRARIES}") -endif() - -set(PC "${Patch_EXECUTABLE}" -p1 -i "${CMAKE_SOURCE_DIR}/thirdparty/soci/sqlite3-path.patch") - -# Build project -ExternalProject_Add( - soci-external - URL "https://github.com/SOCI/soci/archive/4.0.1.tar.gz" - URL_HASH "SHA256=fa69347b1a1ef74450c0382b665a67bd6777cc7005bbe09726479625bcf1e29c" - SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/thirdparty/soci-src" - CMAKE_ARGS ${SOCI_CMAKE_ARGS} - PATCH_COMMAND ${PC} - BUILD_BYPRODUCTS ${SOCI_LIBRARIES_LIST} - EXCLUDE_FROM_ALL TRUE -) - -# Set dependencies -if(NOT WIN32) - add_dependencies(soci-external ODBC::ODBC) -endif() - -# Set variables -set(SOCI_FOUND "YES" CACHE STRING "" FORCE) -set(SOCI_INCLUDE_DIR "${SOCI_BYPRODUCT_DIR}/include" CACHE STRING "" FORCE) -set(SOCI_LIBRARIES "${SOCI_LIBRARIES_LIST}" CACHE STRING "" FORCE) +include(${CMAKE_SOURCE_DIR}/extensions/ExtensionHeader.txt) -# Create imported targets -file(MAKE_DIRECTORY ${SOCI_INCLUDE_DIR}) +include_directories(SYSTEM ../../thirdparty/rapidjson-1.1.0/include/ ../../thirdparty/rapidjson-1.1.0/include/rapidjson) +include_directories(".") -add_library(SOCI::libsoci_core STATIC IMPORTED) -set_target_properties(SOCI::libsoci_core PROPERTIES IMPORTED_LOCATION "${SOCI_BYPRODUCT_DIR}/${LIBDIR}/libsoci_core${BYPRODUCT_SUFFIX}") -set_target_properties(SOCI::libsoci_core PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${SOCI_INCLUDE_DIR}") -add_dependencies(SOCI::libsoci_core soci-external) -target_compile_features(SOCI::libsoci_core INTERFACE cxx_std_14) +file(GLOB SOURCES "*.cpp" "services/*.cpp" "processors/*.cpp" "data/*.cpp") -add_library(SOCI::libsoci_odbc STATIC IMPORTED) -set_target_properties(SOCI::libsoci_odbc PROPERTIES IMPORTED_LOCATION "${SOCI_BYPRODUCT_DIR}/${LIBDIR}/libsoci_odbc${BYPRODUCT_SUFFIX}") -set_target_properties(SOCI::libsoci_odbc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${SOCI_INCLUDE_DIR}") -add_dependencies(SOCI::libsoci_odbc soci-external) -set_property(TARGET SOCI::libsoci_odbc APPEND PROPERTY INTERFACE_LINK_LIBRARIES SOCI::libsoci_core) -set_property(TARGET SOCI::libsoci_odbc APPEND PROPERTY INTERFACE_LINK_LIBRARIES ODBC::ODBC) -target_compile_features(SOCI::libsoci_odbc INTERFACE cxx_std_14) +add_minifi_library(minifi-sql SHARED ${SOURCES}) -target_link_libraries(minifi-sql SOCI::libsoci_odbc SOCI::libsoci_core) +target_link_libraries(minifi-sql SOCI::SOCI) target_link_libraries(minifi-sql ${LIBMINIFI} Threads::Threads) diff --git a/thirdparty/iodbc/all/conandata.yml b/thirdparty/iodbc/all/conandata.yml new file mode 100644 index 0000000000..7cda7fc216 --- /dev/null +++ b/thirdparty/iodbc/all/conandata.yml @@ -0,0 +1,24 @@ +# 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. + +sources: + "3.52.16": + url: "https://github.com/openlink/iODBC/archive/v3.52.16.tar.gz" + sha256: "a0cf0375b462f98c0081c2ceae5ef78276003e57cdf1eb86bd04508fb62a0660" +patches: + "3.52.16": + - patch_file: "patches/GCC-15-needs-typedef-SQLRETURN-HPROC.patch" + patch_description: "GCC 15 needs typedef SQLRETURN (* HPROC) (...)" + patch_type: "portability" diff --git a/thirdparty/iodbc/all/conanfile.py b/thirdparty/iodbc/all/conanfile.py new file mode 100644 index 0000000000..ed5331ca02 --- /dev/null +++ b/thirdparty/iodbc/all/conanfile.py @@ -0,0 +1,96 @@ +# 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. + +import os + +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rm, rmdir +from conan.tools.gnu import Autotools, AutotoolsToolchain +from conan.tools.layout import basic_layout + +required_conan_version = ">=2.0" + + +class IodbcConan(ConanFile): + name = "iodbc" + description = "iODBC is a platform-independent ODBC driver manager (LGPL, with linking exception)" + license = "LGPL-2.0-or-later" + url = "https://github.com/openlink/iODBC" + homepage = "https://www.iodbc.org/" + topics = ("odbc", "driver-manager", "database") + package_type = "static-library" + settings = "os", "arch", "compiler", "build_type" + options = { + "fPIC": [True, False], + } + default_options = { + "fPIC": True, + } + + def export_sources(self): + export_conandata_patches(self) + + def layout(self): + basic_layout(self, src_folder="src") + + def validate(self): + if self.settings.os == "Windows": + raise ConanInvalidConfiguration("iodbc does not support Windows; use the system ODBC driver manager instead") + + def build_requirements(self): + self.tool_requires("libtool/2.4.7") + self.tool_requires("autoconf/2.71") + self.tool_requires("automake/1.16.5") + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def generate(self): + tc = AutotoolsToolchain(self) + if self.options.fPIC: + tc.configure_args.append("--with-pic") + tc.configure_args.append("--enable-static") + tc.configure_args.append("--disable-shared") + # Matches the from-source build (see cmake/BundledIodbc.cmake) + tc.extra_cflags.append("-std=gnu17") + tc.generate() + + def build(self): + apply_conandata_patches(self) + self.run("./autogen.sh", cwd=self.source_folder) + autotools = Autotools(self) + autotools.configure(build_script_folder=self.source_folder) + autotools.make() + + def package(self): + copy(self, "LICENSE*", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) + copy(self, "COPYING*", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) + autotools = Autotools(self) + autotools.install() + rmdir(self, os.path.join(self.package_folder, "bin")) + rmdir(self, os.path.join(self.package_folder, "share")) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + rm(self, "*.la", os.path.join(self.package_folder, "lib")) + + def package_info(self): + # Expose iODBC as a drop-in ODBC provider so consumers relying on + # find_package(ODBC) / ODBC::ODBC (e.g. SOCI) resolve to it. + self.cpp_info.set_property("cmake_find_mode", "both") + self.cpp_info.set_property("cmake_file_name", "ODBC") + self.cpp_info.set_property("cmake_target_name", "ODBC::ODBC") + self.cpp_info.libs = ["iodbc"] + if self.settings.os in ("Linux", "FreeBSD"): + self.cpp_info.system_libs = ["pthread", "dl"] diff --git a/thirdparty/iODBC/GCC-15-needs-typedef-SQLRETURN-HPROC.patch b/thirdparty/iodbc/all/patches/GCC-15-needs-typedef-SQLRETURN-HPROC.patch similarity index 100% rename from thirdparty/iODBC/GCC-15-needs-typedef-SQLRETURN-HPROC.patch rename to thirdparty/iodbc/all/patches/GCC-15-needs-typedef-SQLRETURN-HPROC.patch diff --git a/thirdparty/iodbc/config.yml b/thirdparty/iodbc/config.yml new file mode 100644 index 0000000000..5a867734af --- /dev/null +++ b/thirdparty/iodbc/config.yml @@ -0,0 +1,18 @@ +# 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. + +versions: + "3.52.16": + folder: all diff --git a/thirdparty/soci/all/conandata.yml b/thirdparty/soci/all/conandata.yml new file mode 100644 index 0000000000..98caacfc20 --- /dev/null +++ b/thirdparty/soci/all/conandata.yml @@ -0,0 +1,27 @@ +# 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. + +sources: + "4.1.4": + url: "https://github.com/SOCI/soci/archive/v4.1.4.tar.gz" + sha256: "144f017cccc2e2d806badb3313d6ab3c67a1925bccaa747a46fb3907108a615d" +patches: + "4.1.4": + - patch_file: "patches/disable-sqlwchar-support.patch" + patch_description: "Disable SQLWCHAR support for iODBC" + patch_type: "portability" + - patch_file: "patches/odbc-get-parameter-name-bounds-safe.patch" + patch_description: "Return empty name for positional use elements instead of throwing (fixes out_of_range on execute with positional binds)" + patch_type: "portability" diff --git a/thirdparty/soci/all/conanfile.py b/thirdparty/soci/all/conanfile.py new file mode 100644 index 0000000000..7d81c1c734 --- /dev/null +++ b/thirdparty/soci/all/conanfile.py @@ -0,0 +1,180 @@ +# 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. + +# Recipe based on https://github.com/conan-io/conan-center-index/blob/master/recipes/soci/all/conanfile.py + +from conan import ConanFile +from conan.tools.build import check_min_cppstd +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rmdir +from conan.tools.scm import Version +import os + +required_conan_version = ">=2.1" + + +class SociConan(ConanFile): + name = "soci" + homepage = "https://github.com/SOCI/soci" + url = "https://github.com/conan-io/conan-center-index" + description = "The C++ Database Access Library " + topics = ("mysql", "odbc", "postgresql", "sqlite3") + license = "BSL-1.0" + package_type = "library" + settings = "os", "arch", "compiler", "build_type" + options = { + "shared": [True, False], + "fPIC": [True, False], + "empty": [True, False], + "with_sqlite3": [True, False], + "with_odbc": [True, False], + "with_mysql": [True, False], + "with_postgresql": [True, False], + "with_boost": [True, False], + } + default_options = { + "shared": False, + "fPIC": True, + "empty": False, + "with_sqlite3": False, + "with_odbc": False, + "with_mysql": False, + "with_postgresql": False, + "with_boost": False, + } + + implements = ["auto_shared_fpic"] + + def export_sources(self): + export_conandata_patches(self) + + def layout(self): + cmake_layout(self, src_folder="src") + + def build_requirements(self): + self.tool_requires("cmake/[>=3.23 <4]") + + def requirements(self): + # New versions will not need transitive_headers=True + self.requires("fmt/12.1.0") + if self.options.with_sqlite3: + self.requires("sqlite3/[>=3.44 <4]", transitive_headers=True) + if self.options.with_odbc and self.settings.os != "Windows": + self.requires("iodbc/3.52.16@minifi/develop", transitive_headers=True) + if self.options.with_mysql: + self.requires("libmysqlclient/8.1.0", transitive_headers=True) + if self.options.with_postgresql: + self.requires("libpq/[>=15.4 <18.0]", transitive_headers=True) + if self.options.with_boost: + self.requires("boost/1.83.0", transitive_headers=True) + + def validate(self): + check_min_cppstd(self, 14) + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + apply_conandata_patches(self) + + def generate(self): + tc = CMakeToolchain(self) + # MacOS @rpath + tc.cache_variables["CMAKE_POLICY_DEFAULT_CMP0042"] = "NEW" + tc.cache_variables["SOCI_SHARED"] = self.options.shared + tc.cache_variables["SOCI_STATIC"] = not self.options.shared + tc.cache_variables["SOCI_TESTS"] = False + tc.cache_variables["SOCI_EMPTY"] = self.options.empty + tc.cache_variables["SOCI_LTO"] = False + tc.cache_variables["SOCI_FMT_BUILTIN"] = False + tc.cache_variables["SOCI_SQLITE3"] = self.options.with_sqlite3 + tc.cache_variables["SOCI_DB2"] = False + tc.cache_variables["SOCI_ODBC"] = self.options.with_odbc + tc.cache_variables["SOCI_ORACLE"] = False + tc.cache_variables["SOCI_FIREBIRD"] = False + tc.cache_variables["SOCI_MYSQL"] = self.options.with_mysql + tc.cache_variables["SOCI_POSTGRESQL"] = self.options.with_postgresql + tc.cache_variables["WITH_BOOST"] = self.options.with_boost + tc.generate() + + deps = CMakeDeps(self) + # libmysqlclient: handle different target names in versions 4.0.3 and 4.1.0 + deps.set_property("libmysqlclient", "cmake_file_name", "mysql") + deps.set_property("libmysqlclient", "cmake_additional_variables_prefixes", ["MySQL", "MYSQL"]) + deps.set_property("libmysqlclient", "cmake_target_name", "MySQL::MySQL") + deps.set_property("libpq", "cmake_file_name", "postgresql") + deps.set_property("libpq", "cmake_additional_variables_prefixes", ["POSTGRESQL"]) + deps.set_property("sqlite3", "cmake_file_name", "SQLite3") + deps.set_property("sqlite3", "cmake_additional_variables_prefixes", ["SQLITE3"]) + deps.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy(self, "LICENSE_1_0.txt", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder) + + cmake = CMake(self) + cmake.install() + + rmdir(self, os.path.join(self.package_folder, "lib", "cmake")) + + def package_info(self): + self.cpp_info.set_property("cmake_file_name", "SOCI") + + target_suffix = "" if self.options.shared else "_static" + version = Version(self.version) + lib_suffix = "_{}_{}".format(version.major, version.minor) if self.options.shared and self.settings.os == "Windows" else "" + + # soci_core + self.cpp_info.components["soci_core"].set_property("cmake_target_name", "SOCI::soci_core{}".format(target_suffix)) + self.cpp_info.components["soci_core"].libs = ["soci_core{}".format(lib_suffix)] + self.cpp_info.components["soci_core"].requires = ["fmt::fmt"] + if self.options.with_boost: + self.cpp_info.components["soci_core"].requires.append("boost::headers") + + # soci_empty + if self.options.empty: + self.cpp_info.components["soci_empty"].set_property("cmake_target_name", "SOCI::soci_empty{}".format(target_suffix)) + self.cpp_info.components["soci_empty"].libs = ["soci_empty{}".format(lib_suffix)] + self.cpp_info.components["soci_empty"].requires = ["soci_core"] + + # soci_sqlite3 + if self.options.with_sqlite3: + self.cpp_info.components["soci_sqlite3"].set_property("cmake_target_name", "SOCI::soci_sqlite3{}".format(target_suffix)) + self.cpp_info.components["soci_sqlite3"].libs = ["soci_sqlite3{}".format(lib_suffix)] + self.cpp_info.components["soci_sqlite3"].requires = ["soci_core", "sqlite3::sqlite3"] + + # soci_odbc + if self.options.with_odbc: + self.cpp_info.components["soci_odbc"].set_property("cmake_target_name", "SOCI::soci_odbc{}".format(target_suffix)) + self.cpp_info.components["soci_odbc"].libs = ["soci_odbc{}".format(lib_suffix)] + self.cpp_info.components["soci_odbc"].requires = ["soci_core"] + if self.settings.os == "Windows": + self.cpp_info.components["soci_odbc"].system_libs.append("odbc32") + else: + self.cpp_info.components["soci_odbc"].requires.append("iodbc::iodbc") + + # soci_mysql + if self.options.with_mysql: + self.cpp_info.components["soci_mysql"].set_property("cmake_target_name", "SOCI::soci_mysql{}".format(target_suffix)) + self.cpp_info.components["soci_mysql"].libs = ["soci_mysql{}".format(lib_suffix)] + self.cpp_info.components["soci_mysql"].requires = ["soci_core", "libmysqlclient::libmysqlclient"] + + # soci_postgresql + if self.options.with_postgresql: + self.cpp_info.components["soci_postgresql"].set_property("cmake_target_name", "SOCI::soci_postgresql{}".format(target_suffix)) + self.cpp_info.components["soci_postgresql"].libs = ["soci_postgresql{}".format(lib_suffix)] + self.cpp_info.components["soci_postgresql"].requires = ["soci_core", "libpq::libpq"] diff --git a/thirdparty/soci/all/patches/disable-sqlwchar-support.patch b/thirdparty/soci/all/patches/disable-sqlwchar-support.patch new file mode 100644 index 0000000000..6d2ff2f0a5 --- /dev/null +++ b/thirdparty/soci/all/patches/disable-sqlwchar-support.patch @@ -0,0 +1,31 @@ +According to the issue comment https://github.com/SOCI/soci/issues/1306#issuecomment-3351612844 SQLWCHAR being char32_t with libiodbc is unexpected and is not supported by the SOCI library +This patch disables SQLWCHAR using wstrings and instead uses string type as in previous versions of SOCI. + +diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp +index fcd13593..40d1adba 100644 +--- a/src/backends/odbc/statement.cpp ++++ b/src/backends/odbc/statement.cpp +@@ -423,11 +423,6 @@ void odbc_statement_backend::describe_column(int colNum, + case SQL_BIGINT: + dbtype = is_unsigned == SQL_TRUE ? db_uint64 : db_int64; + break; +- case SQL_WCHAR: +- case SQL_WVARCHAR: +- case SQL_WLONGVARCHAR: +- dbtype = db_wstring; +- break; + case SQL_CHAR: + case SQL_VARCHAR: + case SQL_LONGVARCHAR: +diff --git a/src/backends/odbc/vector-use-type.cpp b/src/backends/odbc/vector-use-type.cpp +index ab7246d9..0d441092 100644 +--- a/src/backends/odbc/vector-use-type.cpp ++++ b/src/backends/odbc/vector-use-type.cpp +@@ -243,7 +243,6 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, + buf_ = new char[maxSize * vecSize * sizeof(SQLWCHAR)]; + memset(buf_, 0, maxSize * vecSize * sizeof(SQLWCHAR)); + +- static_assert(sizeof(SQLWCHAR) == sizeof(char16_t), "unexpected SQLWCHAR size"); + char16_t* pos = reinterpret_cast(buf_); + + for (std::size_t i = 0; i != vecSize; ++i) diff --git a/thirdparty/soci/all/patches/odbc-get-parameter-name-bounds-safe.patch b/thirdparty/soci/all/patches/odbc-get-parameter-name-bounds-safe.patch new file mode 100644 index 0000000000..773898be7d --- /dev/null +++ b/thirdparty/soci/all/patches/odbc-get-parameter-name-bounds-safe.patch @@ -0,0 +1,17 @@ +diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp +--- a/src/backends/odbc/statement.cpp ++++ b/src/backends/odbc/statement.cpp +@@ -344,7 +344,12 @@ + + std::string odbc_statement_backend::get_parameter_name(int index) const + { +- return names_.at(index); ++ // Positional use elements have no entry in names_ (which only holds the ++ // ":name" parameters parsed from the query). Return an empty name for them ++ // instead of throwing, matching the sqlite3/empty backends' behaviour. ++ if (index < 0 || static_cast(index) >= names_.size()) ++ return std::string(); ++ return names_[index]; + } + + std::string odbc_statement_backend::rewrite_for_procedure_call( diff --git a/thirdparty/soci/config.yml b/thirdparty/soci/config.yml new file mode 100644 index 0000000000..40733651bf --- /dev/null +++ b/thirdparty/soci/config.yml @@ -0,0 +1,18 @@ +# 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. + +versions: + "4.1.4": + folder: all diff --git a/thirdparty/soci/sqlite3-path.patch b/thirdparty/soci/sqlite3-path.patch deleted file mode 100644 index 13d8e38e03..0000000000 --- a/thirdparty/soci/sqlite3-path.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff -rupN orig/cmake/modules/FindSQLite3.cmake patched/cmake/modules/FindSQLite3.cmake ---- orig/cmake/modules/FindSQLite3.cmake 2020-10-19 16:59:47 -+++ patched/cmake/modules/FindSQLite3.cmake 2024-02-14 13:05:00 -@@ -17,6 +17,8 @@ find_path(SQLITE3_INCLUDE_DIR - find_path(SQLITE3_INCLUDE_DIR - NAMES sqlite3.h - PATH_PREFIXES sqlite sqlite3 -+ HINTS -+ $ENV{SQLITE_ROOT}/include - PATHS - /usr/include - /usr/local/include -@@ -27,13 +29,14 @@ find_path(SQLITE3_INCLUDE_DIR - $ENV{ProgramFiles}/SQLite3/*/include - $ENV{SystemDrive}/SQLite/*/include - $ENV{SystemDrive}/SQLite3/*/include -- $ENV{SQLITE_ROOT}/include - ${SQLITE_ROOT_DIR}/include - $ENV{OSGEO4W_ROOT}/include) - - set(SQLITE3_NAMES sqlite3_i sqlite3) - find_library(SQLITE3_LIBRARY - NAMES ${SQLITE3_NAMES} -+ HINTS -+ $ENV{SQLITE_ROOT}/lib - PATHS - /usr/lib - /usr/local/lib -@@ -42,7 +45,6 @@ find_library(SQLITE3_LIBRARY - $ENV{ProgramFiles}/SQLite3/*/lib - $ENV{SystemDrive}/SQLite/*/lib - $ENV{SystemDrive}/SQLite3/*/lib -- $ENV{SQLITE_ROOT}/lib - ${SQLITE_ROOT_DIR}/lib - $ENV{OSGEO4W_ROOT}/lib) -