Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 54 additions & 17 deletions .github/workflows/ci-pr-validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ jobs:
fetch-depth: 0
submodules: recursive

- name: Restore vcpkg installed cache
uses: actions/cache@v4
with:
path: build/vcpkg_installed
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json', 'CMakeLists.txt', 'vcpkg-triplets/**') }}
restore-keys: vcpkg-${{ runner.os }}-

- name: Build the project
run: |
cmake -B build -DINTEGRATE_VCPKG=ON -DBUILD_TESTS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
Expand Down Expand Up @@ -117,6 +124,15 @@ jobs:
fetch-depth: 0
submodules: recursive

- name: Restore vcpkg installed cache
uses: actions/cache@v4
with:
path: |
build/vcpkg_installed
build-boost-asio/vcpkg_installed
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json', 'CMakeLists.txt', 'vcpkg-triplets/**') }}
restore-keys: vcpkg-${{ runner.os }}-

- name: Build core libraries
run: |
cmake -B build -DINTEGRATE_VCPKG=ON -DBUILD_TESTS=OFF
Expand Down Expand Up @@ -154,8 +170,8 @@ jobs:

- name: Verify custom vcpkg installation
run: |
mv vcpkg /tmp/
cmake -B build-2 -DINTEGRATE_VCPKG=ON -DCMAKE_TOOLCHAIN_FILE="/tmp/vcpkg/scripts/buildsystems/vcpkg.cmake"
mv vcpkg /tmp/vcpkg-custom
cmake -B build-2 -DINTEGRATE_VCPKG=ON -DCMAKE_TOOLCHAIN_FILE="/tmp/vcpkg-custom/scripts/buildsystems/vcpkg.cmake"

cpp20-build:
name: Build with the C++20 standard
Expand Down Expand Up @@ -206,31 +222,45 @@ jobs:
arch: '-A Win32'

steps:
- name: checkout
uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true

- name: Restore vcpkg and its artifacts.
uses: actions/cache@v3
uses: actions/cache@v4
id: vcpkg-cache
continue-on-error: true
with:
path: |
${{ env.VCPKG_ROOT }}
vcpkg_installed
!${{ env.VCPKG_ROOT }}/.git
!${{ env.VCPKG_ROOT }}/buildtrees
!${{ env.VCPKG_ROOT }}/packages
!${{ env.VCPKG_ROOT }}/downloads
key: |
${{ runner.os }}-${{ matrix.triplet}}-${{ hashFiles( 'vcpkg.json' ) }}
${{ github.workspace }}/vcpkg_installed
${{ env.VCPKG_ROOT }}/downloads
${{ env.VCPKG_ROOT }}/vcpkg.exe
key: ${{ runner.os }}-${{ matrix.triplet }}-vcpkg-${{ hashFiles('vcpkg.json') }}
restore-keys: |
${{ runner.os }}-${{ matrix.triplet }}-vcpkg-
save-always: true

- name: Get vcpkg(windows)
if: ${{ runner.os == 'Windows' && steps.vcpkg-cache.outputs.cache-hit != 'true' }}
shell: pwsh
run: |
cd ${{ github.workspace }}
mkdir build -force
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
mkdir build -Force
# If vcpkg.exe already exists, skip bootstrapping to save time and avoid
# modifying the checked-out vcpkg directory.
if (Test-Path "${{ github.workspace }}\\vcpkg\\vcpkg.exe") {
Write-Host "vcpkg.exe present — skipping bootstrap"
} else {
if (Test-Path vcpkg) {
# If vcpkg was checked out as a submodule it may be shallow; fetch full history
git -C vcpkg fetch --unshallow || true
} else {
git clone https://github.com/Microsoft/vcpkg.git
}
Push-Location vcpkg
.\bootstrap-vcpkg.bat
Pop-Location
}

- name: remove system vcpkg(windows)
if: runner.os == 'Windows'
Expand Down Expand Up @@ -355,6 +385,13 @@ jobs:
fetch-depth: 0
submodules: recursive

- name: Restore vcpkg installed cache
uses: actions/cache@v4
with:
path: build-osx/vcpkg_installed
key: vcpkg-${{ runner.os }}-arm64-${{ hashFiles('vcpkg.json', 'CMakeLists.txt', 'vcpkg-triplets/**') }}
restore-keys: vcpkg-${{ runner.os }}-arm64-

- name: Build libraries
run: ./pkg/mac/build-static-library.sh

Expand Down
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,25 @@ if (INTEGRATE_VCPKG)
find_package(ZLIB REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(protobuf CONFIG REQUIRED)
find_package(absl CONFIG REQUIRED)
find_package(zstd CONFIG REQUIRED)
find_package(Snappy CONFIG REQUIRED)
set(COMMON_LIBS CURL::libcurl
ZLIB::ZLIB
OpenSSL::SSL
OpenSSL::Crypto
protobuf::libprotobuf
absl::base
absl::log
absl::log_internal_message
absl::log_internal_check_op
absl::status
absl::statusor
absl::strings
absl::str_format
absl::time
absl::synchronization
absl::cord
$<IF:$<TARGET_EXISTS:zstd::libzstd_shared>,zstd::libzstd_shared,zstd::libzstd_static>
Snappy::snappy
)
Expand Down
56 changes: 50 additions & 6 deletions LegacyFindPackages.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ if (VCPKG_TRIPLET)
set(CMAKE_PREFIX_PATH "${PROJECT_SOURCE_DIR}/vcpkg_installed/${VCPKG_TRIPLET}")
message(STATUS "Use CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
set(PROTOC_PATH "${CMAKE_PREFIX_PATH}/tools/protobuf/protoc")
if (MSVC)
# vcpkg host tools (protoc, etc.) are always built for the host machine
# architecture (x64 on GitHub Actions), regardless of the target triplet.
# Use find_program to locate protoc.exe across known host tool paths.
find_program(PROTOC_PATH NAMES protoc.exe
PATHS
"${PROJECT_SOURCE_DIR}/vcpkg_installed/x64-windows/tools/protobuf"
"${PROJECT_SOURCE_DIR}/vcpkg_installed/arm64-windows/tools/protobuf"
"${PROJECT_SOURCE_DIR}/vcpkg_installed/${VCPKG_TRIPLET}/tools/protobuf"
NO_DEFAULT_PATH)
if (NOT PROTOC_PATH)
set(PROTOC_PATH "${CMAKE_PREFIX_PATH}/tools/protobuf/protoc.exe")
endif ()
# Set the cache variable so protobuf's CMake module compatibility shim finds it
set(Protobuf_PROTOC_EXECUTABLE "${PROTOC_PATH}" CACHE FILEPATH "protoc executable" FORCE)
endif ()
message(STATUS "Use protoc: ${PROTOC_PATH}")
set(VCPKG_ROOT "${PROJECT_SOURCE_DIR}/vcpkg_installed/${VCPKG_TRIPLET}")
set(VCPKG_DEBUG_ROOT "${VCPKG_ROOT}/debug")
Expand Down Expand Up @@ -51,6 +67,10 @@ if (APPLE AND NOT LINK_STATIC)
# The latest Protobuf dependency on macOS requires the C++17 support and
# it could only be found by the CONFIG mode
set(LATEST_PROTOBUF TRUE)
elseif (MSVC AND VCPKG_TRIPLET)
# protobuf >= 6.x on Windows with vcpkg requires CONFIG mode to resolve
# the protobuf::libprotobuf CMake target and its abseil dependencies
set(LATEST_PROTOBUF TRUE)
else ()
set(LATEST_PROTOBUF FALSE)
endif ()
Expand Down Expand Up @@ -83,8 +103,13 @@ message("OPENSSL_INCLUDE_DIR: " ${OPENSSL_INCLUDE_DIR})
message("OPENSSL_LIBRARIES: " ${OPENSSL_LIBRARIES})

if (LATEST_PROTOBUF)
# See https://github.com/apache/arrow/issues/35987
add_definitions(-DPROTOBUF_USE_DLLS)
if (NOT LINK_STATIC)
# Only needed when protobuf itself is a DLL; static builds must NOT define this
# because it marks symbols as __declspec(dllimport), causing LNK2019 when
# linking against a static libprotobuf.lib.
# See https://github.com/apache/arrow/issues/35987
add_definitions(-DPROTOBUF_USE_DLLS)
endif ()
# Use Config mode to avoid FindProtobuf.cmake does not find the Abseil library
find_package(Protobuf REQUIRED CONFIG)
else ()
Expand Down Expand Up @@ -127,8 +152,10 @@ if (LINK_STATIC AND NOT VCPKG_TRIPLET)
add_definitions(-DCURL_STATICLIB)
endif()
elseif (LINK_STATIC AND VCPKG_TRIPLET)
find_package(Protobuf REQUIRED)
message(STATUS "Found protobuf static library: " ${Protobuf_LIBRARIES})
if (NOT LATEST_PROTOBUF)
find_package(Protobuf REQUIRED)
message(STATUS "Found protobuf static library: " ${Protobuf_LIBRARIES})
endif ()
if (MSVC AND (${CMAKE_BUILD_TYPE} STREQUAL Debug))
find_library(ZLIB_LIBRARIES NAMES zlibd)
else ()
Expand Down Expand Up @@ -264,8 +291,8 @@ if (MSVC)
wldap32.lib
Normaliz.lib)
if (LINK_STATIC)
# add external dependencies of libcurl
set(COMMON_LIBS ${COMMON_LIBS} ws2_32.lib crypt32.lib)
# add external dependencies of libcurl (iphlpapi for if_nametoindex)
set(COMMON_LIBS ${COMMON_LIBS} ws2_32.lib crypt32.lib iphlpapi.lib)
# the default compile options have /MD, which cannot be used to build DLLs that link static libraries
string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
string(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
Expand All @@ -279,6 +306,23 @@ if (MSVC)
message(STATUS "CMAKE_CXX_FLAGS_RELEASE: " ${CMAKE_CXX_FLAGS_RELEASE})
message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO: " ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
endif ()
if (VCPKG_TRIPLET)
# protobuf >= 6.x requires abseil; link it explicitly since MSVC static
# linking does not resolve transitive dependencies automatically
find_package(absl CONFIG REQUIRED)
set(COMMON_LIBS ${COMMON_LIBS}
absl::base
absl::log
absl::log_internal_message
absl::log_internal_check_op
absl::status
absl::statusor
absl::strings
absl::str_format
absl::time
absl::synchronization
absl::cord)
endif ()
else()
set(COMMON_LIBS ${COMMON_LIBS} m)
endif()
Expand Down
1 change: 1 addition & 0 deletions build-support/merge_archives.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ for ITEM in $ITEMS; do
cd ..
done

rm -f $MERGED_LIBRARY
ar -qc $MERGED_LIBRARY $LIBS


11 changes: 9 additions & 2 deletions build-support/merge_archives_vcpkg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ if [[ $# -lt 1 ]]; then
fi

CMAKE_BUILD_DIRECTORY=$1

# libprotoc.a is the protobuf compiler (protoc) tool library, not the runtime.
# It pulls in google::protobuf::compiler::java::* and absl debugging/VDSO symbols
# that are not needed by client code and cannot be satisfied without additional deps.
# libprotobuf-lite.a is a subset of libprotobuf.a and causes duplicate symbols.
EXCLUDE_PATTERN="libprotoc.a\|libprotobuf-lite.a"

if [[ $VCPKG_TRIPLET ]]; then
./merge_archives.sh $CMAKE_BUILD_DIRECTORY/libpulsarwithdeps.a \
$CMAKE_BUILD_DIRECTORY/lib/libpulsar.a \
$(find "$CMAKE_BUILD_DIRECTORY/vcpkg_installed/$VCPKG_TRIPLET" -name "*.a" | grep -v debug)
$(find "$CMAKE_BUILD_DIRECTORY/vcpkg_installed/$VCPKG_TRIPLET" -name "*.a" | grep -v '/debug/' | grep -v "$EXCLUDE_PATTERN")
else
./merge_archives.sh $CMAKE_BUILD_DIRECTORY/libpulsarwithdeps.a \
$CMAKE_BUILD_DIRECTORY/lib/libpulsar.a \
$(find "$CMAKE_BUILD_DIRECTORY/vcpkg_installed" -name "*.a" | grep -v debug)
$(find "$CMAKE_BUILD_DIRECTORY/vcpkg_installed" -name "*.a" | grep -v '/debug/' | grep -v "$EXCLUDE_PATTERN")
fi
55 changes: 51 additions & 4 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,59 @@ if (LINK_STATIC AND BUILD_STATIC_LIB)

add_library(pulsarStaticWithDeps STATIC ${PULSAR_SOURCES})
target_include_directories(pulsarStaticWithDeps PRIVATE ${dlfcn-win32_INCLUDE_DIRS})
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
remove_libtype("${COMMON_LIBS}" "optimized" STATIC_LIBS)
if (VCPKG_TRIPLET)
# Collect ALL vcpkg-installed static archives so every transitive dependency
# (protobuf, abseil, curl, zlib, etc.) is merged into the fat lib without
# requiring manual enumeration of individual targets.
set(_vcpkg_dir "${PROJECT_SOURCE_DIR}/vcpkg_installed/${VCPKG_TRIPLET}")
file(GLOB _release_libs "${_vcpkg_dir}/lib/*.lib")
file(GLOB _debug_libs "${_vcpkg_dir}/debug/lib/*.lib")
# Exclude the protobuf compiler tool and lite runtime (not needed at runtime)
foreach (_excl "libprotoc" "libprotobuf-lite")
list(FILTER _release_libs EXCLUDE REGEX "/${_excl}\\.lib$")
list(FILTER _debug_libs EXCLUDE REGEX "/${_excl}\\.lib$")
endforeach ()
# Build per-lib generator expressions to select debug vs release archive
# for multi-config generators (Visual Studio).
set(_vcpkg_static_libs "")
foreach (_rlib IN LISTS _release_libs)
get_filename_component(_libname "${_rlib}" NAME)
set(_dlib "${_vcpkg_dir}/debug/lib/${_libname}")
if (EXISTS "${_dlib}")
list(APPEND _vcpkg_static_libs "$<IF:$<CONFIG:Debug>,${_dlib},${_rlib}>")
else ()
list(APPEND _vcpkg_static_libs "${_rlib}")
endif ()
endforeach ()
# Also merge Windows system DLL import libs so pulsarWithDeps.lib is fully
# self-contained. lib.exe carries the import records into the archive; the
# final linker then resolves DLL deps without the user listing them.
# lib.exe finds these by name via the LIB env var set up by MSBuild/MSVC.
list(APPEND _vcpkg_static_libs
ws2_32.lib crypt32.lib wldap32.lib Normaliz.lib iphlpapi.lib)
set_property(TARGET pulsarStaticWithDeps PROPERTY STATIC_LIBRARY_OPTIONS ${_vcpkg_static_libs})
else ()
remove_libtype("${COMMON_LIBS}" "debug" STATIC_LIBS)
# Non-vcpkg MSVC static build: resolve COMMON_LIBS entries for lib.exe.
# CMake imported target names cannot be passed to lib.exe directly; replace
# them with $<TARGET_FILE:...> generator expressions.
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
remove_libtype("${COMMON_LIBS}" "optimized" STATIC_LIBS)
else ()
remove_libtype("${COMMON_LIBS}" "debug" STATIC_LIBS)
endif ()
set(RESOLVED_STATIC_LIBS "")
foreach (LIB IN LISTS STATIC_LIBS)
if (TARGET ${LIB})
get_target_property(_LIB_TYPE ${LIB} TYPE)
if (_LIB_TYPE STREQUAL "STATIC_LIBRARY" OR _LIB_TYPE STREQUAL "UNKNOWN_LIBRARY")
list(APPEND RESOLVED_STATIC_LIBS "$<TARGET_FILE:${LIB}>")
endif ()
elseif (IS_ABSOLUTE "${LIB}" AND LIB MATCHES "\\.(lib|a)$")
list(APPEND RESOLVED_STATIC_LIBS "${LIB}")
endif ()
endforeach ()
set_property(TARGET pulsarStaticWithDeps PROPERTY STATIC_LIBRARY_OPTIONS ${RESOLVED_STATIC_LIBS})
endif ()
set_property(TARGET pulsarStaticWithDeps PROPERTY STATIC_LIBRARY_OPTIONS ${STATIC_LIBS})
set_property(TARGET pulsarStaticWithDeps PROPERTY OUTPUT_NAME ${LIB_NAME}WithDeps)
set_property(TARGET pulsarStaticWithDeps PROPERTY VERSION ${LIBRARY_VERSION})
install(TARGETS pulsarStaticWithDeps DESTINATION lib)
Expand Down
9 changes: 3 additions & 6 deletions lib/CurlWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,11 @@
#include <assert.h>
#include <curl/curl.h>

#include <mutex>
#include <string>

namespace pulsar {

struct CurlInitializer {
CurlInitializer() { curl_global_init(CURL_GLOBAL_ALL); }
~CurlInitializer() { curl_global_cleanup(); }
};
static CurlInitializer curlInitializer;

class CurlWrapper {
public:
CurlWrapper() noexcept {}
Expand All @@ -47,6 +42,8 @@ class CurlWrapper {

// It must be called before calling other methods
bool init() {
static std::once_flag initFlag;
std::call_once(initFlag, [] { curl_global_init(CURL_GLOBAL_ALL); });
handle_ = curl_easy_init();
return handle_ != nullptr;
}
Expand Down
6 changes: 3 additions & 3 deletions lib/MessageBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,11 @@ MessageBuilder& MessageBuilder::setReplicationClusters(const std::vector<std::st

MessageBuilder& MessageBuilder::disableReplication(bool flag) {
checkMetadata();
google::protobuf::RepeatedPtrField<std::string> r;
google::protobuf::RepeatedPtrField<std::string>* replicateTo = impl_->metadata.mutable_replicate_to();
replicateTo->Clear();
if (flag) {
r.AddAllocated(new std::string("__local__"));
replicateTo->Add("__local__");
}
r.Swap(impl_->metadata.mutable_replicate_to());
return *this;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/MessageImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ void MessageImpl::setReplicationClusters(const std::vector<std::string>& cluster
}

void MessageImpl::disableReplication(bool flag) {
google::protobuf::RepeatedPtrField<std::string> r;
google::protobuf::RepeatedPtrField<std::string>* replicateTo = metadata.mutable_replicate_to();
replicateTo->Clear();
if (flag) {
r.AddAllocated(new std::string("__local__"));
replicateTo->Add("__local__");
}
r.Swap(metadata.mutable_replicate_to());
}

void MessageImpl::setProperty(const std::string& name, const std::string& value) {
Expand Down
Loading
Loading