Skip to content

Commit ed23c9a

Browse files
authored
feat: clean up LD CMake variables & allow for OpenSSL dynamic link (#255)
This adds documentation of the various options used to control the SDK build. It also cleans up the options by prefixing them with `LD_` and making use of `cmake_dependent_option` to expose only relevant options. The default, hands-off configuration is: - Build the SDK and its unit tests (with sanitizer support) - The SDK artifact is a static library - Build example apps - Static link OpenSSL Users can then tweak away from the default: - Disable unit test build (or disable sanitizers) - Enable contract test build - Disable example app build - Make the SDK artifact a shared library - Link OpenSSL dynamically Finally, to simply disable all testing stuff and just produce the SDK, the common `BUILD_TESTING` flag can be disabled. That'll force any of the testing related flags off - use case is build scripts / package maintainers.
1 parent 0a55e7b commit ed23c9a

File tree

11 files changed

+133
-37
lines changed

11 files changed

+133
-37
lines changed

CMakeLists.txt

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
# Required for Apple Silicon support.
55
cmake_minimum_required(VERSION 3.19)
6+
include(CMakeDependentOption)
67

78
project(
89
LaunchDarklyCPPSDKs
@@ -13,22 +14,63 @@ project(
1314

1415
include(GNUInstallDirs)
1516

17+
option(BUILD_TESTING "Top-level switch for testing. Turn off to disable unit and contract tests." ON)
18+
19+
option(LD_BUILD_SHARED_LIBS "Build the SDKs as shared libraries" OFF)
20+
21+
cmake_dependent_option(LD_BUILD_UNIT_TESTS
22+
"Build the C++ unit tests."
23+
ON # default to enabling unit tests
24+
BUILD_TESTING;NOT LD_BUILD_SHARED_LIBS # only exposed if top-level switch is on, and also only when building
25+
# static libs. This is because we have hidden visibility of symbols by default (to only expose our C API.)
26+
OFF # otherwise, off
27+
)
28+
29+
# If you want to run the unit tests with valgrind, then LD_TESTING_SANITIZERS must of OFF.
30+
cmake_dependent_option(LD_TESTING_SANITIZERS
31+
"Enable sanitizers for unit tests."
32+
ON # default to enabling sanitizers
33+
LD_BUILD_UNIT_TESTS # only expose if unit tests enabled..
34+
OFF # otherwise, off
35+
)
36+
37+
cmake_dependent_option(LD_BUILD_CONTRACT_TESTS
38+
"Build contract test service."
39+
OFF # default to disabling contract tests, since they require running a service
40+
BUILD_TESTING # only expose if top-level switch is on..
41+
OFF # otherwise, off
42+
)
43+
44+
# The general strategy is to produce a fat artifact containing all of our dependencies so users
45+
# only have a single thing to link. We should support this either being a static or shared library.
46+
# Because OpenSSL is a large, and security relevant dependency, we should have a separate option
47+
# to link against that statically or dynamically.
48+
49+
option(LD_DYNAMIC_LINK_OPENSSL
50+
"Dynamically link OpenSSL instead of building with static library"
51+
OFF # default to linking OpenSSL statically
52+
)
53+
54+
option(LD_BUILD_EXAMPLES "Build hello-world examples." ON)
55+
56+
57+
if (LD_BUILD_SHARED_LIBS AND LD_BUILD_UNIT_TESTS)
58+
message(WARNING "LaunchDarkly: unit testing isn't supported while building shared libraries. Switch to static libraries or disable unit tests.")
59+
endif ()
60+
1661
# All projects in this repo should share the same version of 3rd party depends.
1762
# It's the only way to remain sane.
1863
set(CMAKE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
1964
set(CMAKE_CXX_STANDARD 17)
2065

2166
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
2267

23-
option(BUILD_TESTING "Enable C++ unit tests." ON)
2468

25-
# If you want to run the unit tests with valgrind, then TESTING_SANITIZERS must of OFF.
26-
option(TESTING_SANITIZERS "Enable sanitizers for unit tests." ON)
27-
28-
if (BUILD_TESTING)
69+
if (LD_BUILD_UNIT_TESTS)
70+
message(STATUS "LaunchDarkly: building unit tests")
2971
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG")
3072
add_compile_definitions(LAUNCHDARKLY_USE_ASSERT)
31-
if (TESTING_SANITIZERS)
73+
if (LD_TESTING_SANITIZERS)
3274
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
3375
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined -fsanitize=leak")
3476
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
@@ -53,13 +95,22 @@ if (BUILD_TESTING)
5395
enable_testing()
5496
endif ()
5597

56-
set(OPENSSL_USE_STATIC_LIBS ON)
98+
if (LD_DYNAMIC_LINK_OPENSSL)
99+
message(STATUS "LaunchDarkly: searching for shared OpenSSL library")
100+
set(OPENSSL_USE_STATIC_LIBS OFF)
101+
else ()
102+
message(STATUS "LaunchDarkly: searching for static OpenSSL library")
103+
set(OPENSSL_USE_STATIC_LIBS ON)
104+
endif ()
105+
57106
find_package(OpenSSL REQUIRED)
58107
message(STATUS "LaunchDarkly: using OpenSSL v${OPENSSL_VERSION}")
59108

109+
# Even though the main SDK might be a static or shared lib, boost should always statically
110+
# linked into the binary.
60111
set(Boost_USE_STATIC_LIBS ON)
61112

62-
if (BUILD_SHARED_LIBS)
113+
if (NOT LD_BUILD_STATIC_LIBS)
63114
# When building a shared library we hide all symbols
64115
# aside from this we have specifically exported for the C-API.
65116
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
@@ -71,25 +122,24 @@ set(Boost_USE_STATIC_RUNTIME OFF)
71122
find_package(Boost 1.81 REQUIRED COMPONENTS json url coroutine)
72123
message(STATUS "LaunchDarkly: using Boost v${Boost_VERSION}")
73124

74-
add_subdirectory(libs/client-sdk)
75-
76-
set(ORIGINAL_BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}")
77-
set(BUILD_SHARED_LIBS OFF)
125+
include(${CMAKE_FILES}/certify.cmake)
126+
add_subdirectory(vendor/foxy)
78127

79-
# Always build the common libraries as static libs.
128+
# Common, internal, and server-sent-events are built as "object" libraries.
80129
add_subdirectory(libs/common)
81130
add_subdirectory(libs/internal)
82131
add_subdirectory(libs/server-sent-events)
83132

84-
set(ORIGINAL_BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}")
85-
86-
set(BUILD_TESTING OFF)
87-
include(${CMAKE_FILES}/certify.cmake)
88-
add_subdirectory(vendor/foxy)
89-
90-
set(BUILD_TESTING "${ORIGINAL_BUILD_TESTING}")
133+
# Built as static or shared depending on LD_BUILD_STATIC_LIBS variable.
134+
# This target "links" in common, internal, and sse as object libraries.
135+
add_subdirectory(libs/client-sdk)
91136

92-
set(BUILD_SHARED_LIBS "${ORIGINAL_BUILD_SHARED_LIBS}")
137+
if (LD_BUILD_CONTRACT_TESTS)
138+
message(STATUS "LaunchDarkly: building contract tests")
139+
add_subdirectory(contract-tests)
140+
endif ()
93141

94-
add_subdirectory(contract-tests)
95-
add_subdirectory(examples)
142+
if (LD_BUILD_EXAMPLES)
143+
message(STATUS "LaunchDarkly: building examples")
144+
add_subdirectory(examples)
145+
endif ()

examples/hello-c-client/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
1212
find_package(Threads REQUIRED)
1313

1414
add_executable(hello-c main.c)
15-
target_link_libraries(hello-c PRIVATE launchdarkly::client launchdarkly::sse launchdarkly::common Threads::Threads)
15+
target_link_libraries(hello-c PRIVATE launchdarkly::client Threads::Threads)

libs/client-sdk/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ include(FetchContent)
3030
# Add main SDK sources.
3131
add_subdirectory(src)
3232

33-
if (BUILD_TESTING)
33+
if (LD_BUILD_UNIT_TESTS)
3434
add_subdirectory(tests)
3535
endif ()

libs/client-sdk/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,44 @@ gcc -I $(pwd)/include -Llib -fPIE -g main.c liblaunchdarkly-cpp-client.so
6969
The examples here are to help with getting started, but generally speaking the SDK should be incorporated using your
7070
build system (CMake for instance).
7171

72+
### CMake Usage
73+
74+
First, add the SDK to your project:
75+
76+
```cmake
77+
add_subdirectory(path-to-sdk-repo)
78+
```
79+
80+
Currently `find_package` is not yet supported.
81+
82+
This will expose the `launchdarkly::client` target. Next, link the target to your executable or library:
83+
84+
```cmake
85+
target_link_libraries(my-target PRIVATE launchdarkly::client)
86+
```
87+
88+
Various CMake options are available to customize the SDK build.
89+
90+
| Option | Description | Default | Requires |
91+
|---------------------------|----------------------------------------------------------------------------------------|--------------------|-------------------------------------------|
92+
| `BUILD_TESTING` | Coarse-grained switch; turn off to disable all testing and only build the SDK targets. | On | N/A |
93+
| `LD_BUILD_UNIT_TESTS` | Whether C++ unit tests are built. | On | `BUILD_TESTING; NOT LD_BUILD_SHARED_LIBS` |
94+
| `LD_TESTING_SANITIZERS` | Whether sanitizers should be enabled. | On | `LD_BUILD_UNIT_TESTS` |
95+
| `LD_BUILD_CONTRACT_TESTS` | Whether the contract test service (used in CI) is built. | Off | `BUILD_TESTING` |
96+
| `LD_BUILD_EXAMPLES` | Whether example apps (hello world) are built. | On | N/A |
97+
| `LD_BUILD_SHARED_LIBS` | Whether the SDK is built as a static or shared library. | Off (static lib) | N/A |
98+
| `LD_DYNAMIC_LINK_OPENSSL` | Whether OpenSSL be dynamically linked. | Off (static link) | N/A |
99+
100+
**Note:** _if building the SDK as a shared library, then unit tests won't be able to link correctly since the SDK's C++
101+
symbols aren't exposed. To run unit tests, build the SDK as a static library._
102+
103+
Example usage:
104+
105+
```bash
106+
# Build the SDK as a shared library
107+
cmake -GNinja .. -DLD_BUILD_SHARED_LIBS=On
108+
```
109+
72110
Learn more
73111
-----------
74112

libs/client-sdk/src/CMakeLists.txt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ file(GLOB HEADER_LIST CONFIGURE_DEPENDS
33
"${LaunchDarklyCPPClient_SOURCE_DIR}/include/launchdarkly/client_side/*.hpp"
44
)
55

6-
# Automatic library: static or dynamic based on user config.
6+
if (LD_BUILD_SHARED_LIBS)
7+
message(STATUS "LaunchDarkly: building client-sdk as shared library")
8+
add_library(${LIBNAME} SHARED)
9+
else ()
10+
message(STATUS "LaunchDarkly: building client-sdk as static library")
11+
add_library(${LIBNAME} STATIC)
12+
endif ()
713

8-
add_library(${LIBNAME}
14+
target_sources(${LIBNAME} PRIVATE
915
${HEADER_LIST}
1016
data_sources/streaming_data_source.cpp
1117
data_sources/data_source_event_handler.cpp
@@ -43,14 +49,16 @@ add_library(${LIBNAME}
4349
serialization/json_all_flags.cpp
4450
flag_manager/flag_manager.cpp
4551
flag_manager/flag_persistence.cpp
46-
bindings/c/sdk.cpp)
52+
bindings/c/sdk.cpp
53+
)
54+
4755

48-
if (MSVC OR (NOT BUILD_SHARED_LIBS))
56+
if (MSVC OR LD_BUILD_STATIC_LIBS)
4957
target_link_libraries(${LIBNAME}
5058
PUBLIC launchdarkly::common
5159
PRIVATE Boost::headers Boost::json Boost::url launchdarkly::sse launchdarkly::internal foxy)
5260
else ()
53-
# The default static lib builds, for linux, are positition independent.
61+
# The default static lib builds, for linux, are position independent.
5462
# So they do not link into a shared object without issues. So, when
5563
# building shared objects do not link the static libraries and instead
5664
# use the "src.hpp" files for required libraries.

libs/common/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ include(${CMAKE_FILES}/expected.cmake)
3030
# Add main SDK sources.
3131
add_subdirectory(src)
3232

33-
if (BUILD_TESTING)
33+
if (LD_BUILD_UNIT_TESTS)
3434
add_subdirectory(tests)
3535
endif ()

libs/internal/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ include(FetchContent)
2828
# Add main SDK sources.
2929
add_subdirectory(src)
3030

31-
if (BUILD_TESTING)
31+
if (LD_BUILD_UNIT_TESTS)
3232
add_subdirectory(tests)
3333
endif ()

libs/server-sent-events/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ include(FetchContent)
3131

3232
add_subdirectory(src)
3333

34-
if (BUILD_TESTING)
34+
if (LD_BUILD_UNIT_TESTS)
3535
add_subdirectory(tests)
3636
endif ()

scripts/build-release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ cd ..
1717
# Build a dynamic release.
1818
mkdir -p build-dynamic && cd build-dynamic
1919
mkdir -p release
20-
cmake -G Ninja -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTING=OFF -D BUILD_SHARED_LIBS=ON -D CMAKE_INSTALL_PREFIX=./release ..
20+
cmake -G Ninja -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTING=OFF -D LD_BUILD_SHARED_LIBS=ON -D CMAKE_INSTALL_PREFIX=./release ..
2121

2222
cmake --build . --target "$1"
2323
cmake --install .

scripts/build-windows.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ cd ..
2020
# Build a dynamic debug release.
2121
mkdir -p build-dynamic-debug && cd build-dynamic-debug
2222
mkdir -p release
23-
cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug -D BUILD_TESTING=OFF -D BUILD_SHARED_LIBS=ON -D CMAKE_INSTALL_PREFIX=./release ..
23+
cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug -D BUILD_TESTING=OFF -D LD_BUILD_SHARED_LIBS=ON -D CMAKE_INSTALL_PREFIX=./release ..
2424

2525
cmake --build . --target "$1"
2626
cmake --install .

scripts/build.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# ./scripts/build.sh my-build-target ON
66
#
77
# $1 the name of the target. For example "launchdarkly-cpp-common".
8-
# $2 ON/OFF which enables/disables building in a test configuration.
8+
# $2 ON/OFF which enables/disables building in a test configuration (unit tests + contract tests.)
99

1010
function cleanup {
1111
cd ..
@@ -17,6 +17,6 @@ cd build
1717
# script ends.
1818
trap cleanup EXIT
1919

20-
cmake -G Ninja -DCMAKE_COMPILE_WARNING_AS_ERROR=TRUE -D BUILD_TESTING="$2" ..
20+
cmake -G Ninja -D CMAKE_COMPILE_WARNING_AS_ERROR=TRUE -D BUILD_TESTING="$2" -D LD_BUILD_UNIT_TESTS="$2" -D LD_BUILD_CONTRACT_TESTS="$2" ..
2121

2222
cmake --build . --target "$1"

0 commit comments

Comments
 (0)