Skip to content

Commit 2746312

Browse files
committed
PYCBC-1520: Statically link against BoringSSL
Motivation ========== In order to provide better user experience, statically linking against BoringSSL remove the previous dependency of OpenSSL needing to be on the users system. Also, as OpenSSL 1.1 goes EOL soon (Sept 2023), the Python SDK is in a better position w.r.t. dependencies provided in our wheels. Modification ============ Update build system to use hooks placed in the C++ SDK in order to statically link BoringSSL instead of dynamically linking OpenSSL. Results ======= OpenSSL dependency is no longer needed. All tests pass. Change-Id: I20ff5da0414e1e3652753cf20078736f62b902b6 Reviewed-on: https://review.couchbase.org/c/couchbase-python-client/+/196766 Tested-by: Build Bot <[email protected]> Reviewed-by: Sergey Avseyev <[email protected]>
1 parent df83179 commit 2746312

12 files changed

+625
-296
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ couchbase/*.so
1313
couchbase/*.dylib*.*
1414
couchbase/*.dll
1515
couchbase/*.pyd
16+
deps/couchbase-cxx-cache/
1617

1718
# Sphinx
1819
docs/_build/

BUILDING.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Building Couchbase Python Client
2+
3+
>**NOTE:** This is the documentation for the 4.x version of the client. This is mostly compatible with the older 3.x version. Please refer to the *release32* branch for the older 3.x version.
4+
5+
Document under construction. Updates coming soon.

CMakeLists.txt

+154-78
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2016-2022. Couchbase, Inc.
1+
# Copyright 2016-2023. Couchbase, Inc.
22
# All Rights Reserved.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License")
@@ -20,122 +20,198 @@ include(FetchContent)
2020

2121
set(CMAKE_CXX_STANDARD 17)
2222

23-
24-
# MultiThreaded$<$<CONFIG:Debug>:Debug>DLL for /MD compile flag
25-
# MultiThreaded$<$<CONFIG:Debug>:Debug> for /MT compile flag
26-
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
2723
if(WIN32)
24+
# cmake-format: off
25+
# MultiThreaded$<$<CONFIG:Debug>:Debug>DLL for /MD compile flag
26+
# MultiThreaded$<$<CONFIG:Debug>:Debug> for /MT compile flag
27+
# cmake-format: on
28+
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
2829
add_definitions(/bigobj)
2930
add_definitions(-D_WIN32_WINNT=0x0601)
3031
endif()
3132

3233
project(couchbase_client)
3334
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
3435

35-
if (PYTHON_VERSION_EXACT)
36-
set(Python_FIND_VIRTUALENV FIRST)
37-
message("finding python version ${PYTHON_VERSION_EXACT}")
38-
36+
if(PYTHON_VERSION_EXACT)
37+
set(Python_FIND_VIRTUALENV FIRST)
38+
message("finding python version ${PYTHON_VERSION_EXACT}")
3939
else()
40-
set(PYTHON_VERSION_EXACT 3.6)
40+
set(PYTHON_VERSION_EXACT 3.6)
4141
endif()
4242
find_package(Python3 ${PYTHON_VERSION_EXACT} COMPONENTS Interpreter Development.Module)
4343

4444
if(WIN32)
45-
set(PYCBC_C_MOD_SUFFIX ".pyd")
45+
set(PYCBC_C_MOD_SUFFIX ".pyd")
4646
else()
47-
set(PYCBC_C_MOD_SUFFIX ".so")
47+
set(PYCBC_C_MOD_SUFFIX ".so")
4848
endif()
4949

50-
if (OPENSSL_ROOT_DIR)
50+
option(USE_STATIC_BORINGSSL "Statically link BoringSSL instead of dynamically linking OpenSSL" FALSE)
51+
message(STATUS "USE_STATIC_BORINGSSL=${USE_STATIC_BORINGSSL}")
52+
if(NOT USE_STATIC_BORINGSSL)
53+
set(COUCHBASE_CXX_CLIENT_POST_LINKED_OPENSSL
54+
ON
55+
CACHE BOOL "" FORCE)
56+
if(OPENSSL_ROOT_DIR)
5157
message(STATUS "OPENSSL_ROOT_DIR set to ${OPENSSL_ROOT_DIR}, calling finder...")
5258
find_package(OpenSSL REQUIRED)
53-
endif()
59+
endif()
5460

55-
if(OPENSSL_FOUND)
56-
message("OpenSSL found, OPENSSL_ROOT_DIR set to ${OPENSSL_ROOT_DIR}")
57-
else()
61+
if(OPENSSL_FOUND)
62+
message(STATUS "OpenSSL found, OPENSSL_ROOT_DIR set to ${OPENSSL_ROOT_DIR}")
63+
else()
5864
if(WIN32)
59-
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
60-
MESSAGE("++ 64 bit architecture")
61-
set(PKGARCH "amd64")
62-
else()
63-
MESSAGE("++ 32 bit architecture")
64-
set(PKGARCH "win32")
65-
endif()
66-
if(NOT OPENSSL_VERSION)
67-
message("No OpenSSL version set...cannot attempt to download.")
68-
else()
69-
# default version is currently 1.1.1g (see setup.py)
70-
FetchContent_Declare(
71-
openssl
72-
URL https://github.com/python/cpython-bin-deps/archive/openssl-bin-${OPENSSL_VERSION}.zip
73-
)
74-
message("fetching OpenSSL version: ${OPENSSL_VERSION}")
75-
FetchContent_Populate(openssl)
76-
message("Downloaded OpenSSL: ${openssl_SOURCE_DIR}/${PKGARCH}")
77-
set(OPENSSL_ROOT_DIR ${openssl_SOURCE_DIR}/${PKGARCH})
78-
endif()
65+
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
66+
message(STATUS "++ 64 bit architecture")
67+
set(PKGARCH "amd64")
68+
else()
69+
message(STATUS "++ 32 bit architecture")
70+
set(PKGARCH "win32")
71+
endif()
72+
if(NOT OPENSSL_VERSION)
73+
message(STATUS "No OpenSSL version set...cannot attempt to download.")
74+
else()
75+
# default version is currently 1.1.1g (see setup.py)
76+
FetchContent_Declare(openssl
77+
URL https://github.com/python/cpython-bin-deps/archive/openssl-bin-${OPENSSL_VERSION}.zip)
78+
message(STATUS "fetching OpenSSL version: ${OPENSSL_VERSION}")
79+
FetchContent_Populate(openssl)
80+
message(STATUS "Downloaded OpenSSL: ${openssl_SOURCE_DIR}/${PKGARCH}")
81+
set(OPENSSL_ROOT_DIR ${openssl_SOURCE_DIR}/${PKGARCH})
82+
endif()
7983
elseif(APPLE)
80-
# we were not supplied an OPENSSL_ROOT_DIR, so for macos assume brew is how it is installed, if it is...
81-
find_program(BREW_COMMAND brew)
82-
if(BREW_COMMAND)
83-
message(STATUS "brew command: ${BREW_COMMAND}")
84-
execute_process(COMMAND ${BREW_COMMAND} --prefix [email protected] OUTPUT_VARIABLE BREW_OPENSSL_PREFIX RESULT_VARIABLE BREW_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE)
85-
message(STATUS "brew result: ${BREW_RESULT}, prefix: ${BREW_OPENSSL_PREFIX}")
86-
if(BREW_RESULT EQUAL 0)
87-
set(OPENSSL_ROOT_DIR ${BREW_OPENSSL_PREFIX} CACHE INTERNAL "" FORCE)
88-
message(STATUS "brew set OPENSSL_ROOT_DIR to ${OPENSSL_ROOT_DIR}, finding OpenSSL...")
89-
endif()
84+
# we were not supplied an OPENSSL_ROOT_DIR, so for macos assume brew is how it is installed, if it is...
85+
find_program(BREW_COMMAND brew)
86+
if(BREW_COMMAND)
87+
message(STATUS "brew command: ${BREW_COMMAND}")
88+
execute_process(
89+
COMMAND ${BREW_COMMAND} --prefix [email protected]
90+
OUTPUT_VARIABLE BREW_OPENSSL_PREFIX
91+
RESULT_VARIABLE BREW_RESULT
92+
OUTPUT_STRIP_TRAILING_WHITESPACE)
93+
message(STATUS "brew result: ${BREW_RESULT}, prefix: ${BREW_OPENSSL_PREFIX}")
94+
if(BREW_RESULT EQUAL 0)
95+
set(OPENSSL_ROOT_DIR
96+
${BREW_OPENSSL_PREFIX}
97+
CACHE INTERNAL "" FORCE)
98+
message(STATUS "brew set OPENSSL_ROOT_DIR to ${OPENSSL_ROOT_DIR}, finding OpenSSL...")
9099
endif()
100+
endif()
91101
else()
92-
message("Not mac or windows, so assuming OpenSSL v1.1 is installed and findable...")
102+
message(STATUS "Not mac or windows, so assuming OpenSSL v1.1 is installed and findable...")
93103
endif()
94104
find_package(OpenSSL REQUIRED)
105+
endif()
106+
107+
message(STATUS "Adding ${OPENSSL_INCLUDE_DIR} to include dirs...")
108+
include_directories(${OPENSSL_INCLUDE_DIR})
109+
else()
110+
set(COUCHBASE_CXX_CLIENT_POST_LINKED_OPENSSL
111+
OFF
112+
CACHE BOOL "" FORCE)
113+
set(COUCHBASE_CXX_CLIENT_STATIC_BORINGSSL
114+
ON
115+
CACHE BOOL "" FORCE)
116+
endif()
117+
118+
set(COUCHBASE_CXX_CLIENT_PYTHON_WARNINGS
119+
ON
120+
CACHE INTERNAL "")
121+
set(COUCHBASE_CXX_CLIENT_BUILD_TESTS
122+
OFF
123+
CACHE BOOL "" FORCE)
124+
set(COUCHBASE_CXX_CLIENT_BUILD_EXAMPLES
125+
OFF
126+
CACHE BOOL "" FORCE)
127+
set(COUCHBASE_CXX_CLIENT_BUILD_TOOLS
128+
OFF
129+
CACHE BOOL "" FORCE)
130+
131+
# cmake-format: off
132+
# PYCBC-1374 + PYCBC-1495: Move to dynamically link against static stdlib to avoid issues with:
133+
# - other packages that also link against stdlibs (grpc)
134+
# - building SDK on RHEL >= RHEL8 as static stdlibs are not available.
135+
# cmake-format: on
136+
option(USE_STATIC_STDLIB "Statically link C++ standard library" FALSE)
137+
if(USE_STATIC_STDLIB)
138+
set(COUCHBASE_CXX_CLIENT_STATIC_STDLIB
139+
ON
140+
CACHE BOOL "" FORCE)
141+
else()
142+
set(COUCHBASE_CXX_CLIENT_STATIC_STDLIB
143+
OFF
144+
CACHE BOOL "" FORCE)
95145
endif()
146+
message(STATUS "USE_STATIC_STDLIB=${USE_STATIC_STDLIB}")
96147

97-
message("Adding ${OPENSSL_INCLUDE_DIR} to include dirs...")
98-
include_directories(${OPENSSL_INCLUDE_DIR})
99-
100-
set(COUCHBASE_CXX_CLIENT_PYTHON_WARNINGS ON CACHE INTERNAL "")
101-
set(COUCHBASE_CXX_CLIENT_BUILD_TESTS OFF CACHE BOOL "" FORCE)
102-
set(COUCHBASE_CXX_CLIENT_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
103-
set(COUCHBASE_CXX_CLIENT_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
104-
set(COUCHBASE_CXX_CLIENT_POST_LINKED_OPENSSL ON CACHE BOOL "" FORCE)
105-
# PYCBC-1374 - issues finding static stdc++ 64-bit libs on RHEL, provide ability to dynamically link if needed
106-
if(NOT DEFINED ENV{COUCHBASE_CXX_CLIENT_STATIC_STDLIB})
107-
set(COUCHBASE_CXX_CLIENT_STATIC_STDLIB ON CACHE BOOL "" FORCE)
148+
# handle CPM cache dir
149+
if(DEFINED COUCHBASE_CXX_CPM_CACHE_DIR AND NOT COUCHBASE_CXX_CPM_CACHE_DIR STREQUAL "")
150+
set(CPM_SOURCE_CACHE "${COUCHBASE_CXX_CPM_CACHE_DIR}")
108151
endif()
152+
153+
if(DEFINED CPM_SOURCE_CACHE)
154+
message(STATUS "CPM_SOURCE_CACHE=${CPM_SOURCE_CACHE}")
155+
endif()
156+
109157
add_subdirectory(deps/couchbase-cxx-client)
110158

111-
set(CB_CXX_DIR "${PROJECT_SOURCE_DIR}/deps/couchbase-cxx-client")
159+
set(COUCHBASE_CXX_BINARY_DIR "${CMAKE_BINARY_DIR}/deps/couchbase-cxx-client")
160+
message(STATUS "COUCHBASE_CXX_BINARY_DIR=${COUCHBASE_CXX_BINARY_DIR}")
161+
if(DEFINED COUCHBASE_CXX_CPM_CACHE_DIR AND NOT COUCHBASE_CXX_CPM_CACHE_DIR STREQUAL "")
162+
file(COPY "${COUCHBASE_CXX_BINARY_DIR}/mozilla-ca-bundle.crt" "${COUCHBASE_CXX_BINARY_DIR}/mozilla-ca-bundle.sha256"
163+
DESTINATION "${COUCHBASE_CXX_CPM_CACHE_DIR}")
164+
message(STATUS "Copied Mozilla cert bundle to cache. COUCHBASE_CXX_CPM_CACHE_DIR=${COUCHBASE_CXX_CPM_CACHE_DIR}")
165+
endif()
112166

113167
if(Python3_FOUND)
114-
message("Python executable: ${Python3_EXECUTABLE}")
115-
message("Python include dir: ${Python3_INCLUDE_DIRS}")
116-
message("Python libs: ${Python3_LIBRARIES}")
168+
message(STATUS "Python executable: ${Python3_EXECUTABLE}")
169+
message(STATUS "Python include dir: ${Python3_INCLUDE_DIRS}")
170+
message(STATUS "Python libs: ${Python3_LIBRARIES}")
117171
else()
118-
message(FATAL_ERROR "Python3 not found.")
172+
message(FATAL_ERROR "Python3 not found.")
119173
endif()
120174

121175
include_directories(SYSTEM ${Python3_INCLUDE_DIRS})
122-
include_directories(BEFORE "${CB_CXX_DIR}/include")
123-
include_directories(BEFORE "${CB_CXX_DIR}/third_party/asio/asio/include")
124-
file(GLOB SOURCE_FILES "src/*.cxx" "src/management/*.cxx" "src/transactions/*.cxx")
176+
file(
177+
GLOB
178+
SOURCE_FILES
179+
"src/*.cxx"
180+
"src/management/*.cxx"
181+
"src/transactions/*.cxx")
125182
add_library(pycbc_core SHARED ${SOURCE_FILES})
126183

184+
target_include_directories(pycbc_core PRIVATE "${CB_CXX_DIR}/include" "${CB_CXX_DIR}/third_party/asio/asio/include")
185+
127186
if(WIN32)
128-
target_link_libraries(pycbc_core couchbase_cxx_client ${Python3_LIBRARIES} ${OPENSSL_LIBRARIES})
187+
target_link_libraries(
188+
pycbc_core
189+
PRIVATE couchbase_cxx_client
190+
${Python3_LIBRARIES}
191+
asio
192+
Microsoft.GSL::GSL
193+
taocpp::json)
129194
else()
130-
target_link_libraries(pycbc_core couchbase_cxx_client ${OPENSSL_LIBRARIES})
131-
if(APPLE)
132-
target_link_options(pycbc_core PRIVATE -undefined dynamic_lookup)
133-
endif()
195+
target_link_libraries(pycbc_core PRIVATE couchbase_cxx_client asio Microsoft.GSL::GSL taocpp::json)
196+
if(APPLE)
197+
target_link_options(
198+
pycbc_core
199+
PRIVATE
200+
-undefined
201+
dynamic_lookup)
202+
endif()
203+
endif()
204+
205+
if(CMAKE_VERBOSE_MAKEFILE)
206+
target_link_options(pycbc_core PRIVATE -v)
207+
endif()
208+
209+
if(NOT USE_STATIC_BORINGSSL)
210+
target_link_libraries(pycbc_core PUBLIC ${OPENSSL_LIBRARIES})
134211
endif()
135212

136-
set_target_properties(pycbc_core
137-
PROPERTIES
138-
PREFIX ""
139-
OUTPUT_NAME pycbc_core
140-
SUFFIX ${PYCBC_C_MOD_SUFFIX}
141-
)
213+
set_target_properties(
214+
pycbc_core
215+
PROPERTIES PREFIX ""
216+
OUTPUT_NAME pycbc_core
217+
SUFFIX ${PYCBC_C_MOD_SUFFIX})

0 commit comments

Comments
 (0)