Fix Protobuf symbols not found in libpulsarwithdeps.a when building on macOS (#354)

### Motivation

https://github.com/apache/pulsar-client-cpp/pull/290 brings a regression
that on macOS, Protobuf is always found with CMake Config mode, which
does not set the `Protobuf_LIBRARIES` variable so that the
libpulsarwithdeps.a misses the symbols of Protobuf.

### Modifications

When `LINK_STATIC` is ON, use CMake Module mode to find the Protobuf.

Add `build-static-library.sh` to build libraries with static
dependencies and verify these libraries in PR workflow. Upload the
pre-built binaries in the build workflow.

(cherry picked from commit f75b39bcbaad63ed96268fe7e09993e0e6a8a959)
diff --git a/.github/workflows/ci-build-binary-artifacts.yaml b/.github/workflows/ci-build-binary-artifacts.yaml
index 586458d..a2b7be8 100644
--- a/.github/workflows/ci-build-binary-artifacts.yaml
+++ b/.github/workflows/ci-build-binary-artifacts.yaml
@@ -192,3 +192,34 @@
         with:
           name: ${{ matrix.triplet }}-Debug
           path: ${{ env.INSTALL_DIR }}-Debug
+
+  package-macos:
+    name: Build macOS libraries
+    runs-on: macos-latest
+    timeout-minutes: 500
+
+    strategy:
+      fail-fast: false
+      matrix:
+        arch: [x86_64, arm64]
+
+    steps:
+      - name: checkout
+        uses: actions/checkout@v3
+
+      - name: Install dependencies
+        run: |
+          export ARCH=${{ matrix.arch }}
+          ./pkg/mac/build-static-library.sh
+
+      - name: Zip artifact
+        run: |
+          cd ./pkg/mac/.install
+          zip -r macos-${{ matrix.arch }}.zip ./include/pulsar/* ./lib/*
+          cp macos-${{ matrix.arch }}.zip ../../../
+
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        with:
+          name: macos-${{ matrix.arch }}.zip
+          path: macos-${{ matrix.arch }}.zip
diff --git a/.github/workflows/ci-pr-validation.yaml b/.github/workflows/ci-pr-validation.yaml
index 03d417f..80e1a1d 100644
--- a/.github/workflows/ci-pr-validation.yaml
+++ b/.github/workflows/ci-pr-validation.yaml
@@ -302,6 +302,28 @@
         run: |
           cmake --build ./build-macos --parallel --config Release
 
+  cpp-build-macos-static:
+    timeout-minutes: 120
+    name: Build CPP Client on macOS with static dependencies
+    runs-on: macos-12
+    needs: unit-tests
+    steps:
+      - name: checkout
+        uses: actions/checkout@v3
+
+      - name: Build libraries
+        run: ./pkg/mac/build-static-library.sh
+
+      - name: Test static libraries
+        run: |
+          export PULSAR_DIR=$PWD/pkg/mac/.install
+          echo "Build with static library"
+          clang++ win-examples/example.cc -o static.out -std=c++11 -I $PULSAR_DIR/include $PULSAR_DIR/lib/libpulsarwithdeps.a
+          ./static.out
+          echo "Build with dynamic library"
+          clang++ win-examples/example.cc -o dynamic.out -std=c++11 -I $PULSAR_DIR/include -L $PULSAR_DIR/lib -Wl,-rpath $PULSAR_DIR/lib -lpulsar
+          ./dynamic.out
+
   # Job that will be required to complete and depends on all the other jobs
   check-completion:
     name: Check Completion
diff --git a/.gitignore b/.gitignore
index a569bda..a1e5224 100644
--- a/.gitignore
+++ b/.gitignore
@@ -104,3 +104,5 @@
 .tests-container-id.txt
 Testing
 .test-token.txt
+pkg/mac/.build
+pkg/mac/.install
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8d6a00..fb4f1b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,9 +88,17 @@
 MESSAGE(STATUS "Threads library: " ${CMAKE_THREAD_LIBS_INIT})
 
 set(Boost_NO_BOOST_CMAKE ON)
+
+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)
+else ()
+    set(LATEST_PROTOBUF FALSE)
+endif ()
+
 if (NOT CMAKE_CXX_STANDARD)
-    if (APPLE)
-        # The latest Protobuf dependency on macOS requires the C++17 support
+    if (LATEST_PROTOBUF)
         set(CMAKE_CXX_STANDARD 17)
     else ()
         set(CMAKE_CXX_STANDARD 11)
@@ -143,7 +151,7 @@
 message("OPENSSL_INCLUDE_DIR: " ${OPENSSL_INCLUDE_DIR})
 message("OPENSSL_LIBRARIES: " ${OPENSSL_LIBRARIES})
 
-if (APPLE)
+if (LATEST_PROTOBUF)
     # See https://github.com/apache/arrow/issues/35987
     add_definitions(-DPROTOBUF_USE_DLLS)
     # Use Config mode to avoid FindProtobuf.cmake does not find the Abseil library
@@ -318,7 +326,7 @@
   ${CMAKE_DL_LIBS}
 )
 
-if (APPLE)
+if (LATEST_PROTOBUF)
     # Protobuf_LIBRARIES is empty when finding Protobuf in Config mode
     set(COMMON_LIBS ${COMMON_LIBS} protobuf::libprotobuf)
 else ()
diff --git a/dependencies.yaml b/dependencies.yaml
index f206ccc..18be438 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -23,5 +23,5 @@
 zlib: 1.2.12
 zstd: 1.5.2
 snappy: 1.1.9
-openssl: 1.1.1q
+openssl: 1.1.1v
 curl: 8.4.0
diff --git a/pkg/mac/build-static-library.sh b/pkg/mac/build-static-library.sh
new file mode 100755
index 0000000..f0253fb
--- /dev/null
+++ b/pkg/mac/build-static-library.sh
@@ -0,0 +1,190 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -ex
+cd `dirname $0`
+
+pip3 install pyyaml
+
+MACOSX_DEPLOYMENT_TARGET=10.15
+if [[ -z ${ARCH} ]]; then
+    ARCH=`uname -m`
+fi
+
+BUILD_DIR=$PWD/.build
+INSTALL_DIR=$PWD/.install
+PREFIX=$BUILD_DIR/install
+mkdir -p $BUILD_DIR
+cp -f ../../build-support/dep-version.py $BUILD_DIR/
+cp -f ../../dependencies.yaml $BUILD_DIR/
+
+pushd $BUILD_DIR
+
+BOOST_VERSION=$(./dep-version.py boost)
+ZLIB_VERSION=$(./dep-version.py zlib)
+OPENSSL_VERSION=$(./dep-version.py openssl)
+PROTOBUF_VERSION=$(./dep-version.py protobuf)
+ZSTD_VERSION=$(./dep-version.py zstd)
+SNAPPY_VERSION=$(./dep-version.py snappy)
+CURL_VERSION=$(./dep-version.py curl)
+
+BOOST_VERSION_=${BOOST_VERSION//./_}
+if [ ! -f boost/.done ]; then
+    echo "Building Boost $BOOST_VERSION"
+    curl -O -L https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_}.tar.gz
+    tar zxf boost_${BOOST_VERSION_}.tar.gz
+    mkdir -p $PREFIX/include
+    cp -rf boost_${BOOST_VERSION_}/boost $PREFIX/include/
+    mkdir -p boost
+    touch boost/.done
+else
+    echo "Using cached Boost $BOOST_VERSION"
+fi
+
+if [ ! -f zlib-${ZLIB_VERSION}/.done ]; then
+    echo "Building ZLib $ZLIB_VERSION"
+    curl -O -L https://zlib.net/fossils/zlib-${ZLIB_VERSION}.tar.gz
+    tar zxf zlib-${ZLIB_VERSION}.tar.gz
+    pushd zlib-$ZLIB_VERSION
+      CFLAGS="-fPIC -O3 -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" ./configure --prefix=$PREFIX
+      make -j16
+      make install
+      touch .done
+    popd
+else
+    echo "Using cached ZLib $ZLIB_VERSION"
+fi
+
+OPENSSL_VERSION_UNDERSCORE=$(echo $OPENSSL_VERSION | sed 's/\./_/g')
+if [ ! -f openssl-OpenSSL_${OPENSSL_VERSION_UNDERSCORE}.done ]; then
+    echo "Building OpenSSL $OPENSSL_VERSION"
+    curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_$OPENSSL_VERSION_UNDERSCORE.tar.gz
+    tar zxf OpenSSL_$OPENSSL_VERSION_UNDERSCORE.tar.gz
+
+    pushd openssl-OpenSSL_${OPENSSL_VERSION_UNDERSCORE}
+      if [[ $ARCH = 'arm64' ]]; then
+          PLATFORM=darwin64-arm64-cc
+      else
+          PLATFORM=darwin64-x86_64-cc
+      fi
+      CFLAGS="-fPIC -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
+          ./Configure --prefix=$PREFIX no-shared no-unit-test $PLATFORM
+      make -j8 >/dev/null
+      make install_sw >/dev/null
+    popd
+
+    touch openssl-OpenSSL_${OPENSSL_VERSION_UNDERSCORE}.done
+else
+    echo "Using cached OpenSSL $OPENSSL_VERSION"
+fi
+
+if [ ! -f protobuf-${PROTOBUF_VERSION}/.done ]; then
+    echo "Building Protobuf $PROTOBUF_VERSION"
+    curl -O -L https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
+    tar zxf protobuf-cpp-${PROTOBUF_VERSION}.tar.gz
+    pushd protobuf-${PROTOBUF_VERSION}
+      pushd cmake/
+        # Build protoc that can run on both x86 and arm architectures
+        cmake -B build -DCMAKE_CXX_FLAGS="-fPIC -arch x86_64 -arch arm64 -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
+            -Dprotobuf_BUILD_TESTS=OFF \
+            -DCMAKE_INSTALL_PREFIX=$PREFIX
+        cmake --build build -j16 --target install
+      popd
+
+      # Retain the library for one architecture so that `ar` can work on the library
+      pushd $PREFIX/lib
+        mv libprotobuf.a libprotobuf_universal.a
+        lipo libprotobuf_universal.a -thin ${ARCH} -output libprotobuf.a
+      popd
+      touch .done
+    popd
+else
+    echo "Using cached Protobuf $PROTOBUF_VERSION"
+fi
+
+if [ ! -f zstd-${ZSTD_VERSION}/.done ]; then
+    echo "Building ZStd $ZSTD_VERSION"
+    curl -O -L https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}/zstd-${ZSTD_VERSION}.tar.gz
+    tar zxf zstd-${ZSTD_VERSION}.tar.gz
+    pushd zstd-${ZSTD_VERSION}
+      CFLAGS="-fPIC -O3 -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" PREFIX=$PREFIX \
+            make -j16 -C lib install-static install-includes
+      touch .done
+    popd
+else
+    echo "Using cached ZStd $ZSTD_VERSION"
+fi
+
+if [ ! -f snappy-${SNAPPY_VERSION}/.done ]; then
+    echo "Building Snappy $SNAPPY_VERSION"
+    curl -O -L https://github.com/google/snappy/archive/refs/tags/${SNAPPY_VERSION}.tar.gz
+    tar zxf ${SNAPPY_VERSION}.tar.gz
+    pushd snappy-${SNAPPY_VERSION}
+      CXXFLAGS="-fPIC -O3 -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
+          cmake . -DCMAKE_INSTALL_PREFIX=$PREFIX -DSNAPPY_BUILD_TESTS=OFF -DSNAPPY_BUILD_BENCHMARKS=OFF
+      make -j16
+      make install
+      touch .done
+    popd
+else
+    echo "Using cached Snappy $SNAPPY_VERSION"
+fi
+
+if [ ! -f curl-${CURL_VERSION}/.done ]; then
+    echo "Building LibCurl $CURL_VERSION"
+    CURL_VERSION_=${CURL_VERSION//./_}
+    curl -O -L https://github.com/curl/curl/releases/download/curl-${CURL_VERSION_}/curl-${CURL_VERSION}.tar.gz
+    tar zxf curl-${CURL_VERSION}.tar.gz
+    pushd curl-${CURL_VERSION}
+      # Force the compiler to find the OpenSSL headers instead of the headers in the system path like /usr/local/include/openssl.
+      cp -rf $PREFIX/include/openssl include/
+      CFLAGS="-I$PREFIX/include -fPIC -arch ${ARCH} -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" \
+            ./configure --with-ssl=$PREFIX \
+              --without-nghttp2 \
+              --without-libidn2 \
+              --disable-ldap \
+              --without-brotli \
+              --without-secure-transport \
+              --without-librtmp \
+              --disable-ipv6 \
+              --host=$ARCH-apple-darwin \
+              --prefix=$PREFIX
+      make -j16 install
+      touch .done
+    popd
+else
+    echo "Using cached LibCurl $CURL_VERSION"
+fi
+
+popd # pkg/mac
+cd ../../ # project root
+
+cmake -B build-static -DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET \
+    -DLINK_STATIC=ON \
+    -DBUILD_TESTS=OFF \
+    -DBUILD_DYNAMIC_LIB=ON \
+    -DBUILD_STATIC_LIB=ON \
+    -DCMAKE_OSX_ARCHITECTURES=${ARCH} \
+    -DCMAKE_PREFIX_PATH=$PREFIX \
+    -DOPENSSL_ROOT_DIR=$PREFIX \
+    -DPROTOC_PATH=$PREFIX/bin/protoc \
+    -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \
+    -DCMAKE_BUILD_TYPE=Release
+cmake --build build-static -j16 --target install