Skip to content

Commit

Permalink
Fix Protobuf symbols not found in libpulsarwithdeps.a when building o…
Browse files Browse the repository at this point in the history
…n macOS

### Motivation

#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.
  • Loading branch information
BewareMyPower committed Nov 21, 2023
1 parent 37ea769 commit a5dc8a6
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 5 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/ci-build-binary-artifacts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,34 @@ jobs:
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
22 changes: 22 additions & 0 deletions .github/workflows/ci-pr-validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,28 @@ jobs:
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
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,5 @@ vcpkg_installed/
.tests-container-id.txt
Testing
.test-token.txt
pkg/mac/.build
pkg/mac/.install
16 changes: 12 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,17 @@ find_package(Threads REQUIRED)
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)
Expand Down Expand Up @@ -143,7 +151,7 @@ find_package(OpenSSL REQUIRED)
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
Expand Down Expand Up @@ -318,7 +326,7 @@ set(COMMON_LIBS
${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 ()
Expand Down
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ protobuf: 3.20.0
zlib: 1.2.12
zstd: 1.5.2
snappy: 1.1.9
openssl: 1.1.1q
openssl: 1.1.1v
curl: 8.4.0
190 changes: 190 additions & 0 deletions pkg/mac/build-static-library.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit a5dc8a6

Please sign in to comment.