Skip to content

Conversation

@BewareMyPower
Copy link
Contributor

@BewareMyPower BewareMyPower commented Oct 9, 2022

Motivation

Currently, even with LINK_STATIC=ON option, dynamic libraries could still be linked. For example, on macOS, the following libcurl library will be found:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/lib/libcurl.tbd

Then, the libpulsar.dylib will link to /usr/lib/libcurl.4.dylib, which is not a static library.

Modifications

When LINK_STATIC is enabled, change CMAKE_FIND_LIBRARY_SUFFIXES to .a for non-MSVC compilers so that only static libraries could be found except OpenSSL, which should not be linked statically.

In addition, use find_package as much as possible instead of raw usages of find_path and find_library.

Documentation

  • doc-required
    (Your PR needs to update docs and you will update later)

  • doc-not-needed
    (Please explain why)

  • doc
    (Your PR contains doc changes)

  • doc-complete
    (Docs have been already added)

### Motivation

Currently, even with `LINK_STATIC=ON` option, dynamic libraries could
still be linked. For example, on macOS, the following libcurl library
will be found:

```
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/lib/libcurl.tbd
```

Then, the `libpulsar.dylib` will link to `/usr/lib/libcurl.4.dylib`,
which is not a dynamic library.

### Modifications

When `LINK_STATIC` is enabled, change `CMAKE_FIND_LIBRARY_SUFFIXES` to
`.a` for non-MSVC compilers so that only static libraries could be
found except OpenSSL, which should not be linked statically.

In addition, use `find_package` as much as possible instead of raw
usages of `find_path` and `find_library`.
@BewareMyPower BewareMyPower self-assigned this Oct 9, 2022
@BewareMyPower BewareMyPower marked this pull request as draft October 9, 2022 06:35
@BewareMyPower BewareMyPower marked this pull request as ready for review October 9, 2022 07:21
@BewareMyPower
Copy link
Contributor Author

@merlimat @Demogorgon314 @RobertIndie Now all tests passed, PTAL.

Currently I'm working on fixing the Windows build when LINK_STATIC is ON, which might be based on this PR. Because when LINK_STATIC is ON, no Windows dependencies could be found because the suffix is not .a. This PR accidentally fixes some issues of finding dependencies. Regarding other issues to build statically linked Windows library, will push another PR later.

@merlimat merlimat merged commit 4451cbd into apache:main Oct 9, 2022
@BewareMyPower BewareMyPower deleted the bewaremypower/enhance-cmake branch October 9, 2022 15:36
@merlimat
Copy link
Contributor

merlimat commented Oct 9, 2022

@BewareMyPower CMake is now failing to find OpenSSL on Mac (installed with brew):

CMake Error at /opt/homebrew/Cellar/cmake/3.23.0/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the
  system variable OPENSSL_ROOT_DIR (missing: OPENSSL_CRYPTO_LIBRARY
  OPENSSL_INCLUDE_DIR)
Call Stack (most recent call first):
  /opt/homebrew/Cellar/cmake/3.23.0/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  /opt/homebrew/Cellar/cmake/3.23.0/share/cmake/Modules/FindOpenSSL.cmake:578 (find_package_handle_standard_args)
  CMakeLists.txt:127 (find_package)

@BewareMyPower
Copy link
Contributor Author

@merlimat I just tested again in my local env.

Here is my command (just test the default LINK_STATIC option because it does not affect OpenSSL):

cmake -Wno-dev \
    -DCMAKE_PREFIX_PATH="/usr/local" \
    -DBUILD_TESTS=OFF -DBUILD_PERF_TOOLS=ON \
    -B build

Here are my outputs after this PR:

-- Found OpenSSL: /opt/local/lib/libcrypto.dylib (found version "3.0.4")  
-- Found OpenSSL: /opt/local/lib/libcrypto.dylib (found version "3.0.4")  
RECORD_OPENSSL_SSL_LIBRARY: /opt/local/lib/libssl.dylib
RECORD_OPENSSL_CRYPTO_LIBRARY: /opt/local/lib/libcrypto.dylib
-- Found OpenSSL: /usr/local/opt/openssl/lib/libcrypto.dylib (found version "3.0.4")  
OPENSSL_INCLUDE_DIR: /usr/local/opt/openssl/include//opt/homebrew/opt/openssl/include
OPENSSL_SSL_LIBRARY: /usr/local/opt/openssl/lib/libssl.dylib
OPENSSL_CRYPTO_LIBRARY: /usr/local/opt/openssl/lib/libcrypto.dylib

Here are my outputs before this PR (just added the same logs):

-- Found OpenSSL: /usr/local/opt/openssl/lib/libcrypto.dylib   
RECORD_OPENSSL_SSL_LIBRARY: /usr/local/opt/openssl/lib/libssl.dylib
RECORD_OPENSSL_CRYPTO_LIBRARY: /usr/local/opt/openssl/lib/libcrypto.dylib
OPENSSL_INCLUDE_DIR: /usr/local/opt/openssl/include//opt/homebrew/opt/openssl/include
OPENSSL_SSL_LIBRARY: /usr/local/opt/openssl/lib/libssl.dylib
OPENSSL_CRYPTO_LIBRARY: /usr/local/opt/openssl/lib/libcrypto.dylib

The patch to add logs:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d3876f8..5952576 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -135,6 +135,8 @@ set(OPENSSL_USE_STATIC_LIBS FALSE)
 find_package(OpenSSL REQUIRED)
 set(RECORD_OPENSSL_SSL_LIBRARY ${OPENSSL_SSL_LIBRARY})
 set(RECORD_OPENSSL_CRYPTO_LIBRARY ${OPENSSL_CRYPTO_LIBRARY})
+message("RECORD_OPENSSL_SSL_LIBRARY: " ${RECORD_OPENSSL_SSL_LIBRARY})
+message("RECORD_OPENSSL_CRYPTO_LIBRARY: " ${RECORD_OPENSSL_CRYPTO_LIBRARY})
 
 unset(OPENSSL_FOUND CACHE)
 unset(OPENSSL_INCLUDE_DIR CACHE)
@@ -270,6 +272,9 @@ endif()
 find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
 
 find_package(OpenSSL REQUIRED)
+message("OPENSSL_INCLUDE_DIR: " ${OPENSSL_INCLUDE_DIR})
+message("OPENSSL_SSL_LIBRARY: " ${OPENSSL_SSL_LIBRARY})
+message("OPENSSL_CRYPTO_LIBRARY: " ${OPENSSL_CRYPTO_LIBRARY})
 
 if (BUILD_TESTS)
     find_path(GTEST_INCLUDE_PATH gtest/gtest.h)

It looks like this PR brings some unexpected changes, I will investigate and fix it soon.

@merlimat
Copy link
Contributor

merlimat commented Oct 9, 2022

I think there’s one extra find_package for OpenSSL at the beginning (3 calls in total). It should be removed.

Additionally, we should still use static lib for OpenSSL too

@BewareMyPower
Copy link
Contributor Author

Additionally, we should still use static lib for OpenSSL too

It is exactly what I am confused. From https://pulsar.apache.org/docs/client-libraries-cpp#install-dependencies

The libpulsarwithdeps.a does not include library openssl related libraries libssl and libcrypto, because these two libraries are related to security. It is more reasonable and easier to use the versions provided by the local system to handle security issues and upgrade libraries.

I also found the original PR (apache/pulsar#6458) from @jiazhai.

Because if there is a security problem in libssl, all the machines can just update their own libssl library without rebuilding libpulsar.a.

Should we revert these complicated logic to find and link OpenSSL dependency?

@merlimat
Copy link
Contributor

merlimat commented Oct 9, 2022

I think that if we don't do that, there can be linking problems between different OpenSSL version (eg: 1.1.1 vs 3.0.4)

@BewareMyPower
Copy link
Contributor Author

if we don't do that, there can be linking problems between different OpenSSL version (eg: 1.1.1 vs 3.0.4)

Yeah, I agree. The ABI compatibility changed a lot, see https://abi-laboratory.pro/?view=timeline&l=openssl

In addition,

libpulsar.so is a shared library, containing statically linked boost and openssl.

libpulsarnossl.so is a shared library, similar to libpulsar.so except that the libraries openssl and crypto are dynamically linked.

I think we should remove libpulsarnossl.so and link statically to openssl in libpulsarwithdeps.a, right? @merlimat

BewareMyPower added a commit to BewareMyPower/pulsar-client-cpp that referenced this pull request Oct 9, 2022
### Motivation

See discussions here: apache#28 (comment)

The original purpose to not include static OpenSSL library in
`libpulsarwithnossl.so` and `libpulsarwithdeps.a` is
apache/pulsar#6458. However, the ABI
compatibility of OpenSSL is not good. If the Pulsar C++ library links
dynamically to OpenSSL and the user only changes the OpenSSL dynamic
library, some symbols might not be found.

### Modifications

Use `LINK_STATIC` option to determine whether to link to OpenSSL library
statically. After that, there are only 3 libraries generated when
`LINK_STATIC` is ON.
- `libpulsar.so`: the dynamic pulsar-client-cpp library.
- `libpulsar.a`: the static pulsar-client-cpp library. When it's used,
  users must link to all 3rd party dependencies (OpenSSL, curl, etc.)
- `libpulsarwithdeps.a`: the static pulsar-client-cpp library.
merlimat pushed a commit that referenced this pull request Oct 10, 2022
* Link to OpenSSL statically when LINK_STATIC is ON

### Motivation

See discussions here: #28 (comment)

The original purpose to not include static OpenSSL library in
`libpulsarwithnossl.so` and `libpulsarwithdeps.a` is
apache/pulsar#6458. However, the ABI
compatibility of OpenSSL is not good. If the Pulsar C++ library links
dynamically to OpenSSL and the user only changes the OpenSSL dynamic
library, some symbols might not be found.

### Modifications

Use `LINK_STATIC` option to determine whether to link to OpenSSL library
statically. After that, there are only 3 libraries generated when
`LINK_STATIC` is ON.
- `libpulsar.so`: the dynamic pulsar-client-cpp library.
- `libpulsar.a`: the static pulsar-client-cpp library. When it's used,
  users must link to all 3rd party dependencies (OpenSSL, curl, etc.)
- `libpulsarwithdeps.a`: the static pulsar-client-cpp library.

* Remove unnecessary code

* Remove libpulsarnossl.so build
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants