From 0234fb7552991ae821efa1355fd18416f153a16b Mon Sep 17 00:00:00 2001 From: Josh Bradshaw Date: Wed, 25 Feb 2026 14:52:52 -0500 Subject: [PATCH 1/4] Migrate qtnats build to vcpkg-compatible CMake with install targets Remove FetchContent for cnats and use find_package(cnats CONFIG) instead. Add proper install() rules and CMake package config so qtnats can be consumed as a vcpkg overlay port. Update includes for cnats v3.10.1 () and replace private opts.h constants with hardcoded values. Co-Authored-By: Claude Opus 4.6 --- CMakeLists.txt | 90 ++++++++++++++++++++++-------------- cmake/qtnats-config.cmake.in | 10 ++++ src/qtnats/qtnats.cpp | 21 ++++----- src/qtnats/qtnats.h | 4 +- 4 files changed, 78 insertions(+), 47 deletions(-) create mode 100644 cmake/qtnats-config.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 12c7787..04408bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,35 +1,17 @@ cmake_minimum_required(VERSION 3.16) -project(QtNatsProject) +project(QtNatsProject VERSION 0.1.0) include(CMakePrintHelpers) -include(FetchContent) include(GenerateExportHeader) - -set(default_build_type "Release") +include(GNUInstallDirs) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_AUTOMOC ON) -message("Using Qt version ${QT_VERSION}") - -# show that we're git-cloning cnats -set(FETCHCONTENT_QUIET FALSE) -FetchContent_Declare( - cnats - URL https://github.com/nats-io/nats.c/archive/refs/tags/v3.3.0.tar.gz -) - -set(NATS_BUILD_WITH_TLS ON) -set(NATS_BUILD_EXAMPLES OFF) -set(NATS_BUILD_STREAMING OFF) -set(NATS_BUILD_LIB_SHARED OFF) - -set(BUILD_TESTING OFF) # do not build cnats tests -set(BUILD_QT_NATS_INTEGRATION_TESTING OFF) - -FetchContent_MakeAvailable(cnats) +find_package(cnats CONFIG REQUIRED) +find_package(Qt6 REQUIRED COMPONENTS Core) # ------------- qtnats library ---------------------- add_library(qtnats @@ -38,25 +20,69 @@ add_library(qtnats src/qtnats/qtnats.cpp src/qtnats/qtnats.h src/qtnats/qtnats_p.h - ${CMAKE_CURRENT_BINARY_DIR}/qtnats_export.h + ${CMAKE_CURRENT_BINARY_DIR}/qtnats/qtnats_export.h ) target_include_directories(qtnats PUBLIC - src - ${CMAKE_CURRENT_BINARY_DIR} - ${cnats_SOURCE_DIR}/src + $ + $ + $ ) +target_link_libraries(qtnats PUBLIC cnats::nats_static Qt6::Core) -target_link_libraries(qtnats nats_static Qt::Core) +set_target_properties(qtnats PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 0.1 + EXPORT_NAME qtnats +) -# this has no effect on Windows due to https://gitlab.kitware.com/cmake/cmake/-/issues/19618 -set_target_properties(qtnats PROPERTIES VERSION 0.1.0 SOVERSION 0.1) +GENERATE_EXPORT_HEADER(qtnats + EXPORT_FILE_NAME qtnats/qtnats_export.h +) -GENERATE_EXPORT_HEADER(qtnats) +# ------------- install rules ---------------------- +install(TARGETS qtnats + EXPORT qtnats-targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +install(FILES + src/qtnats/qtnats.h + src/qtnats/qtnats_p.h + ${CMAKE_CURRENT_BINARY_DIR}/qtnats/qtnats_export.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qtnats +) + +install(EXPORT qtnats-targets + NAMESPACE qtnats:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats +) + +include(CMakePackageConfigHelpers) + +configure_package_config_file( + cmake/qtnats-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats +) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config-version.cmake + COMPATIBILITY SameMajorVersion +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats +) # integration tests (these spin up nats server and nats client) +set(BUILD_QT_NATS_INTEGRATION_TESTING OFF CACHE BOOL "Build qtnats integration tests") if (BUILD_QT_NATS_INTEGRATION_TESTING) add_executable(test_core test/test_core.cpp) add_test(NAME test_core COMMAND test_core) @@ -66,7 +92,3 @@ if (BUILD_QT_NATS_INTEGRATION_TESTING) add_test(NAME test_jetstream COMMAND test_jetstream) target_link_libraries(test_jetstream PRIVATE qtnats Qt::Test) endif () - -if(COMMAND dc_register_thirdparty_library) - dc_register_thirdparty_library(qtnats) -endif() diff --git a/cmake/qtnats-config.cmake.in b/cmake/qtnats-config.cmake.in new file mode 100644 index 0000000..83a6dda --- /dev/null +++ b/cmake/qtnats-config.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +find_dependency(cnats CONFIG) +find_dependency(Qt6 COMPONENTS Core) + +include("${CMAKE_CURRENT_LIST_DIR}/qtnats-targets.cmake") + +check_required_components(qtnats) diff --git a/src/qtnats/qtnats.cpp b/src/qtnats/qtnats.cpp index 60d4f05..3954333 100644 --- a/src/qtnats/qtnats.cpp +++ b/src/qtnats/qtnats.cpp @@ -4,8 +4,6 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use 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 - #include #include @@ -31,15 +29,16 @@ void QtNats::checkError(natsStatus s) Options::Options() { - // don't want to include opts.h in qtnats.h - timeout = NATS_OPTS_DEFAULT_TIMEOUT; - pingInterval = NATS_OPTS_DEFAULT_PING_INTERVAL; - maxPingsOut = NATS_OPTS_DEFAULT_MAX_PING_OUT; - ioBufferSize = NATS_OPTS_DEFAULT_IO_BUF_SIZE; - maxReconnect = NATS_OPTS_DEFAULT_MAX_RECONNECT; - reconnectWait = NATS_OPTS_DEFAULT_RECONNECT_WAIT; - reconnectBufferSize = NATS_OPTS_DEFAULT_RECONNECT_BUF_SIZE; - maxPendingMessages = NATS_OPTS_DEFAULT_MAX_PENDING_MSGS; + // These defaults mirror the cnats opts.h constants. + // We hardcode them to avoid depending on the private cnats header. + timeout = 2000; // NATS_OPTS_DEFAULT_TIMEOUT (ms) + pingInterval = 120000; // NATS_OPTS_DEFAULT_PING_INTERVAL (ms) + maxPingsOut = 2; // NATS_OPTS_DEFAULT_MAX_PING_OUT + ioBufferSize = 32768; // NATS_OPTS_DEFAULT_IO_BUF_SIZE + maxReconnect = 60; // NATS_OPTS_DEFAULT_MAX_RECONNECT + reconnectWait = 2000; // NATS_OPTS_DEFAULT_RECONNECT_WAIT (ms) + reconnectBufferSize = 8 * 1024 * 1024; // NATS_OPTS_DEFAULT_RECONNECT_BUF_SIZE + maxPendingMessages = 65536; // NATS_OPTS_DEFAULT_MAX_PENDING_MSGS } static natsOptions* buildNatsOptions(const Options& opts) diff --git a/src/qtnats/qtnats.h b/src/qtnats/qtnats.h index 588d1e0..ce7d6d6 100644 --- a/src/qtnats/qtnats.h +++ b/src/qtnats/qtnats.h @@ -18,9 +18,9 @@ Unless required by applicable law or agreed to in writing, software distributed #include #include -#include +#include -#include +#include namespace QtNats { From 05f9ec0eb1a5322ec94eb1e13d823bf8f36579e5 Mon Sep 17 00:00:00 2001 From: Josh Bradshaw Date: Wed, 25 Feb 2026 15:55:50 -0500 Subject: [PATCH 2/4] Add FetchContent fallback for cnats when not available via find_package Allow qtnats to build both with vcpkg (where cnats is pre-installed and found via find_package) and without vcpkg (where cnats is automatically fetched via FetchContent). The target name difference between the two paths (cnats::nats_static vs nats_static) is handled via a CNATS_TARGET variable. Co-Authored-By: Claude Opus 4.6 --- CMakeLists.txt | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 04408bf..4d69177 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,29 @@ set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_AUTOMOC ON) -find_package(cnats CONFIG REQUIRED) +find_package(cnats CONFIG QUIET) +if(NOT cnats_FOUND) + message(STATUS "cnats not found via find_package, fetching via FetchContent...") + include(FetchContent) + FetchContent_Declare(cnats + URL https://github.com/nats-io/nats.c/archive/refs/tags/v3.10.1.tar.gz + URL_HASH SHA256=1765533bbc1270ab7c89e3481b4778db7d1e7b4db2fa906b6602cd5c02846222 + ) + set(NATS_BUILD_WITH_TLS ON CACHE BOOL "" FORCE) + set(NATS_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + set(NATS_BUILD_STREAMING OFF CACHE BOOL "" FORCE) + set(BUILD_TESTING_SAVED "${BUILD_TESTING}") + set(BUILD_TESTING OFF CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(cnats) + set(BUILD_TESTING "${BUILD_TESTING_SAVED}" CACHE BOOL "" FORCE) +endif() + +if(TARGET cnats::nats_static) + set(CNATS_TARGET cnats::nats_static) +else() + set(CNATS_TARGET nats_static) +endif() + find_package(Qt6 REQUIRED COMPONENTS Core) # ------------- qtnats library ---------------------- @@ -30,7 +52,7 @@ target_include_directories(qtnats $ ) -target_link_libraries(qtnats PUBLIC cnats::nats_static Qt6::Core) +target_link_libraries(qtnats PUBLIC ${CNATS_TARGET} Qt6::Core) set_target_properties(qtnats PROPERTIES VERSION ${PROJECT_VERSION} From c8f96ea8f12b360f140bb6c50b9c899e02a0a78f Mon Sep 17 00:00:00 2001 From: Josh Bradshaw Date: Thu, 26 Feb 2026 13:30:44 -0500 Subject: [PATCH 3/4] Fix CMake export conflict when cnats is fetched via FetchContent cnats's CMakeLists.txt exports nats_static into multiple export sets, causing a CMake error when qtnats's install(EXPORT) references it as a dependency. Fix by using EXCLUDE_FROM_ALL to suppress cnats's install rules and skipping qtnats install/export when cnats is fetched, since FetchContent consumers use add_subdirectory and don't need install targets. Co-Authored-By: Claude Opus 4.6 --- CMakeLists.txt | 72 ++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d69177..f842955 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,10 @@ if(NOT cnats_FOUND) set(NATS_BUILD_STREAMING OFF CACHE BOOL "" FORCE) set(BUILD_TESTING_SAVED "${BUILD_TESTING}") set(BUILD_TESTING OFF CACHE BOOL "" FORCE) - FetchContent_MakeAvailable(cnats) + FetchContent_Populate(cnats) + add_subdirectory(${cnats_SOURCE_DIR} ${cnats_BINARY_DIR} EXCLUDE_FROM_ALL) set(BUILD_TESTING "${BUILD_TESTING_SAVED}" CACHE BOOL "" FORCE) + set(CNATS_FETCHED TRUE) endif() if(TARGET cnats::nats_static) @@ -65,43 +67,49 @@ GENERATE_EXPORT_HEADER(qtnats ) # ------------- install rules ---------------------- -install(TARGETS qtnats - EXPORT qtnats-targets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +# Install/export rules require cnats from find_package (e.g. vcpkg). +# When cnats is fetched via FetchContent, skip these to avoid conflicts +# with cnats's own export sets. FetchContent consumers use add_subdirectory +# and don't need install targets. +if(NOT CNATS_FETCHED) + install(TARGETS qtnats + EXPORT qtnats-targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) -install(FILES - src/qtnats/qtnats.h - src/qtnats/qtnats_p.h - ${CMAKE_CURRENT_BINARY_DIR}/qtnats/qtnats_export.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qtnats -) + install(FILES + src/qtnats/qtnats.h + src/qtnats/qtnats_p.h + ${CMAKE_CURRENT_BINARY_DIR}/qtnats/qtnats_export.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qtnats + ) -install(EXPORT qtnats-targets - NAMESPACE qtnats:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats -) + install(EXPORT qtnats-targets + NAMESPACE qtnats:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats + ) -include(CMakePackageConfigHelpers) + include(CMakePackageConfigHelpers) -configure_package_config_file( - cmake/qtnats-config.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats -) + configure_package_config_file( + cmake/qtnats-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats + ) -write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config-version.cmake - COMPATIBILITY SameMajorVersion -) + write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config-version.cmake + COMPATIBILITY SameMajorVersion + ) -install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config.cmake - ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config-version.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats -) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/qtnats-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qtnats + ) +endif() # integration tests (these spin up nats server and nats client) set(BUILD_QT_NATS_INTEGRATION_TESTING OFF CACHE BOOL "Build qtnats integration tests") From 54419ce39ecdd837fe4e84153b9fb0a72cfa7fef Mon Sep 17 00:00:00 2001 From: Josh Bradshaw Date: Thu, 26 Feb 2026 17:06:02 -0500 Subject: [PATCH 4/4] Use cnats v3.3.0 and fix FetchContent include path for Downgrade FetchContent fallback from cnats v3.10.1 to v3.3.0 with updated SHA256 hash. Add a wrapper header shim so that #include resolves correctly under both vcpkg (where headers install to include/nats/) and FetchContent (where the build interface exposes headers directly in src/). Co-Authored-By: Claude Opus 4.6 --- CMakeLists.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f842955..d7a4003 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ if(NOT cnats_FOUND) message(STATUS "cnats not found via find_package, fetching via FetchContent...") include(FetchContent) FetchContent_Declare(cnats - URL https://github.com/nats-io/nats.c/archive/refs/tags/v3.10.1.tar.gz - URL_HASH SHA256=1765533bbc1270ab7c89e3481b4778db7d1e7b4db2fa906b6602cd5c02846222 + URL https://github.com/nats-io/nats.c/archive/refs/tags/v3.3.0.tar.gz + URL_HASH SHA256=16e700d912034faefb235a955bd920cfe4d449a260d0371b9694d722eb617ae1 ) set(NATS_BUILD_WITH_TLS ON CACHE BOOL "" FORCE) set(NATS_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) @@ -26,6 +26,15 @@ if(NOT cnats_FOUND) FetchContent_Populate(cnats) add_subdirectory(${cnats_SOURCE_DIR} ${cnats_BINARY_DIR} EXCLUDE_FROM_ALL) set(BUILD_TESTING "${BUILD_TESTING_SAVED}" CACHE BOOL "" FORCE) + + # cnats exposes at build time, but vcpkg installs it as . + # Create a wrapper so #include works in both cases. + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cnats_include/nats") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cnats_include/nats/nats.h" + "#include \n") + target_include_directories(nats_static PUBLIC + $) + set(CNATS_FETCHED TRUE) endif()