Skip to content

Commit 1ca48d5

Browse files
authored
feat: preliminary find_package support (#452)
This PR adds preliminary support for: ```cmake find_package(launchdarkly REQUIRED) target_link_libraries(app PRIVATE launchdarkly::{launchdarkly-cpp-server,launchdarkly-cpp-client} ) ``` It treats the C++ monorepo as the installable unit. In the very near future, this will likely be refactored so that we have two packages. If you want both on the same host, you'd need to install both (and there'd be some redundancy.) Currently there is only one version, `0.1.0`. This isn't updated by release-please. For these two reasons, I'm indicating that this is preliminary and subject to change form.
1 parent f10543e commit 1ca48d5

File tree

26 files changed

+301
-94
lines changed

26 files changed

+301
-94
lines changed

.github/actions/cmake-test/action.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ inputs:
1212
description: 'Boost toolset'
1313
required: false
1414

15-
1615
runs:
1716
using: composite
1817
steps:
@@ -36,6 +35,15 @@ runs:
3635
# along in the same manner to those test projects via the command line.
3736
BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }}
3837
OPENSSL_ROOT_DIR: ${{ steps.install-openssl.outputs.OPENSSL_ROOT_DIR }}
38+
CMAKE_INSTALL_PREFIX: ../LAUNCHDARKLY_INSTALL
39+
- name: Build the SDK
40+
shell: bash
41+
run: |
42+
cmake --build build
43+
- name: Install the SDK
44+
shell: bash
45+
run: |
46+
cmake --install build
3947
- name: Run CMake Integration Tests
4048
shell: bash
4149
run: |

CMakeLists.txt

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.19)
66
include(CMakeDependentOption)
77

88
project(
9-
LaunchDarklyCPPSDKs
9+
launchdarkly
1010
VERSION 0.1
1111
DESCRIPTION "LaunchDarkly C++ SDK Monorepo (Server/Client)"
1212
LANGUAGES CXX C
@@ -21,8 +21,6 @@ if (POLICY CMP0144)
2121
cmake_policy(SET CMP0144 NEW)
2222
endif ()
2323

24-
include(GNUInstallDirs)
25-
2624
option(BUILD_TESTING "Top-level switch for testing. Turn off to disable unit and contract tests." ON)
2725

2826
option(LD_BUILD_SHARED_LIBS "Build the SDKs as shared libraries" OFF)
@@ -99,6 +97,14 @@ set(CMAKE_CXX_STANDARD 17)
9997

10098
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
10199

100+
include(GNUInstallDirs)
101+
set(LD_TARGETS_EXPORT_NAME ${PROJECT_NAME}Targets)
102+
set(LD_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
103+
set(LD_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}")
104+
set(LD_CMAKE_PROJECT_CONFIG_FILE "${LD_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
105+
set(LD_CMAKE_VERSION_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
106+
107+
102108
if (LD_BUILD_UNIT_TESTS)
103109
message(STATUS "LaunchDarkly: building unit tests")
104110
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG")
@@ -155,12 +161,14 @@ endif ()
155161

156162
set(Boost_USE_MULTITHREADED ON)
157163
set(Boost_USE_STATIC_RUNTIME OFF)
164+
158165
find_package(Boost 1.81 REQUIRED COMPONENTS json url coroutine)
159166
message(STATUS "LaunchDarkly: using Boost v${Boost_VERSION}")
160167

161-
include(${CMAKE_FILES}/certify.cmake)
168+
set(FOXY_BUILD_TESTING OFF)
162169
add_subdirectory(vendor/foxy)
163170

171+
164172
# Common, internal, and server-sent-events are built as "object" libraries.
165173
add_subdirectory(libs/common)
166174
add_subdirectory(libs/internal)
@@ -185,3 +193,25 @@ if (LD_BUILD_EXAMPLES)
185193
message(STATUS "LaunchDarkly: building examples")
186194
add_subdirectory(examples)
187195
endif ()
196+
197+
198+
# Support installation of a cmake package.
199+
include(CMakePackageConfigHelpers)
200+
201+
write_basic_package_version_file(
202+
${LD_CMAKE_VERSION_CONFIG_FILE}
203+
COMPATIBILITY SameMajorVersion
204+
)
205+
206+
install(FILES
207+
${LD_CMAKE_PROJECT_CONFIG_FILE}
208+
${LD_CMAKE_VERSION_CONFIG_FILE}
209+
DESTINATION ${LD_CONFIG_INSTALL_DIR}
210+
)
211+
212+
213+
install(
214+
EXPORT ${LD_TARGETS_EXPORT_NAME}
215+
NAMESPACE ${PROJECT_NAME}::
216+
DESTINATION ${LD_CONFIG_INSTALL_DIR}
217+
)

README.md

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ GoogleTest is used for testing.
4949

5050
For information on integrating an SDK package please refer to the SDK specific README.
5151

52-
## CMake Usage
52+
## CMake Options
5353

5454
Various CMake options are available to customize the client/server SDK builds.
5555

@@ -66,30 +66,59 @@ Various CMake options are available to customize the client/server SDK builds.
6666
| `LD_DYNAMIC_LINK_OPENSSL` | Whether OpenSSL is dynamically linked or not. | Off (static link) | N/A |
6767
| `LD_BUILD_REDIS_SUPPORT` | Whether the server-side Redis Source is built or not. | Off | N/A |
6868

69-
**Note:** _if building the SDKs as shared libraries, then unit tests won't be able to link correctly since the SDK's C++
70-
symbols aren't exposed. To run unit tests, build a static library._
71-
7269
> [!WARNING]
7370
> When building shared libraries C++ symbols are not exported, only the C API will be exported. This is because C++ does
74-
> not have a stable ABI.
71+
> not have a stable ABI. For this reason, the SDK's unit tests are not built in shared library mode.
72+
73+
## Building the SDK from Source
7574

76-
Basic usage example:
75+
To configure the SDK's CMake project:
7776

7877
```bash
79-
mkdir -p build && cd build
80-
cmake -G"Unix Makefiles" ..
78+
# Use 'make' as the build system.
79+
cmake -B build -S . -G"Unix Makefiles"
8180
```
8281

83-
Slightly more advanced example - build shared libraries, and don't build any of the testing components:
82+
To pass in config options defined in the table above, add them using `-D`:
8483

8584
```bash
86-
mkdir -p build && cd build
87-
cmake -G"Unix Makefiles" -DLD_BUILD_SHARED_LIBS=On -DBUILD_TESTING=Off ..
85+
# Use 'make' as the build system, build shared libs, and disable testing.
86+
cmake -B build -S . -G"Unix Makefiles" \
87+
-DLD_BUILD_SHARED_LIBS=On \
88+
-DBUILD_TESTING=Off ..
8889
```
8990

9091
The example uses `make`, but you might instead use [Ninja](https://ninja-build.org/),
9192
MSVC, [etc.](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
9293

94+
## Incorporating the SDK via `add_subdirectory`
95+
96+
The SDK can be incorporated into an existing application using CMake via `add_subdirectory.`.
97+
98+
```cmake
99+
# Set SDK build options, for example:
100+
set(LD_BUILD_SHARED_LIBS On)
101+
102+
add_subdirectory(path-to-cpp-sdks-repo)
103+
target_link_libraries(your-app PRIVATE launchdarkly::client)
104+
# ... or launchdarkly::server
105+
````
106+
107+
## Incorporating the SDK via `find_package`
108+
109+
> [!WARNING]
110+
> Preliminary support for `find_package` is available. The package configuration is subject to change, do not expect it
111+
> to be stable as long as this notice is present.
112+
113+
If you've installed the SDK on the build system via `cmake --install`, you can consume it from
114+
the target application like so:
115+
116+
```cmake
117+
find_package(launchdarkly REQUIRED)
118+
target_link_libraries(your-app PRIVATE launchdarkly::launchdarkly-cpp-client)
119+
# ... or launchdarkly::launchdarkly-cpp-server
120+
```
121+
93122
## LaunchDarkly overview
94123

95124
[LaunchDarkly](https://www.launchdarkly.com) is a feature management platform that serves trillions of feature flags

cmake-tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include(declareProjectTest.cmake)
2+
add_subdirectory(test_find_package)
23
add_subdirectory(test_add_subdirectory)

cmake-tests/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,10 @@ Additionally, certain variables must be forwarded to each test project CMake con
6262

6363
Checks that a project can include the SDK as a sub-project, via `add_subdirectory`.
6464
This would be a likely use-case when the repo is a submodule of another project.
65+
66+
### cmake_projects/test_find_package
67+
68+
Checks that a project can include the SDK via `find_package(ldserverapi)`.
69+
This would be a likely use-case if the SDK was installed on the system by the user.
70+
71+
**NOTE:** Requires SDK to be installed.

cmake-tests/declareProjectTest.cmake

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ macro(declare_find_package_test name)
7575
NAME ${test_prefix}_configure
7676
COMMAND
7777
${CMAKE_COMMAND}
78-
# Since project/CMakeLists.txt uses find_package(), it needs to know where to find
79-
# ldserverapiConfig.cmake. That can be found where the SDK is installed, which is CMAKE_INSTALL_PREFIX.
80-
-DCMAKE_PREFIX_PATH=${CMAKE_INSTALL_PREFIX}
78+
# The project under test is going to use find_package() to find the launchdarkly SDK. The package config
79+
# is going to in turn find_package() for boost. So, we need to pass in the location of the SDK's package
80+
# config file, as well as boost's.
81+
"-DCMAKE_PREFIX_PATH=${CMAKE_INSTALL_PREFIX};${BOOST_ROOT}"
8182
${CMAKE_CURRENT_SOURCE_DIR}/project
8283
)
8384

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This test assumes that the SDK has been installed at CMAKE_INSTALL_PREFIX.
2+
declare_find_package_test(test_find_package)
3+
add_build_step(test_find_package)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cmake_minimum_required(VERSION 3.19)
2+
3+
project(UseFindPackageTest)
4+
5+
find_package(launchdarkly REQUIRED)
6+
7+
add_executable(use_find_package_server main_server.cpp)
8+
target_link_libraries(use_find_package_server launchdarkly::launchdarkly-cpp-server)
9+
10+
11+
add_executable(use_find_package_client main_client.cpp)
12+
target_link_libraries(use_find_package_client launchdarkly::launchdarkly-cpp-client)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <launchdarkly/client_side/client.hpp>
2+
#include <launchdarkly/context_builder.hpp>
3+
4+
#include <cstring>
5+
#include <iostream>
6+
7+
using namespace launchdarkly;
8+
using namespace launchdarkly::client_side;
9+
10+
int main() {
11+
auto config = ConfigBuilder("sdk-key").Build();
12+
if (!config) {
13+
std::cout << "error: config is invalid: " << config.error() << '\n';
14+
return 1;
15+
}
16+
17+
auto context =
18+
ContextBuilder().Kind("user", "example-user-key").Name("Sandy").Build();
19+
20+
auto client = Client(std::move(*config), std::move(context));
21+
22+
client.StartAsync();
23+
24+
std::cout << client.Initialized() << '\n';
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <launchdarkly/server_side/client.hpp>
2+
#include <launchdarkly/server_side/config/config_builder.hpp>
3+
4+
#include <cstring>
5+
#include <iostream>
6+
7+
using namespace launchdarkly;
8+
using namespace launchdarkly::server_side;
9+
10+
int main() {
11+
auto config = ConfigBuilder("sdk-key").Build();
12+
if (!config) {
13+
std::cout << "error: config is invalid: " << config.error() << '\n';
14+
return 1;
15+
}
16+
17+
auto client = Client(std::move(*config));
18+
19+
client.StartAsync();
20+
21+
std::cout << client.Initialized() << '\n';
22+
23+
}

cmake/certify.cmake

Lines changed: 0 additions & 23 deletions
This file was deleted.

cmake/googletest.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ FetchContent_Declare(googletest
1313
)
1414
# For Windows: Prevent overriding the parent project's compiler/linker settings
1515
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
16+
17+
# Disable installation of googletest
18+
set(INSTALL_GTEST OFF CACHE BOOL "Disable googletest installation" FORCE)
19+
1620
FetchContent_MakeAvailable(googletest)

cmake/launchdarkly-cpp-clientConfig.cmake

Lines changed: 0 additions & 8 deletions
This file was deleted.

cmake/launchdarklyConfig.cmake

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
include(CMakeFindDependencyMacro)
2+
3+
if (NOT DEFINED Boost_USE_STATIC_LIBS)
4+
if (LD_DYNAMIC_LINK_BOOST)
5+
set(Boost_USE_STATIC_LIBS OFF)
6+
else ()
7+
set(Boost_USE_STATIC_LIBS ON)
8+
endif ()
9+
endif ()
10+
11+
find_dependency(Boost 1.81 COMPONENTS json url coroutine)
12+
find_dependency(OpenSSL)
13+
find_dependency(tl-expected)
14+
find_dependency(certify)
15+
16+
include(${CMAKE_CURRENT_LIST_DIR}/launchdarklyTargets.cmake)

cmake/rfc3339_timestamp.cmake

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FetchContent_Declare(timestamp
22
GIT_REPOSITORY https://github.com/chansen/c-timestamp
33
GIT_TAG "b205c407ae6680d23d74359ac00444b80989792f"
4-
)
4+
)
55

66
FetchContent_GetProperties(timestamp)
77
if (NOT timestamp_POPULATED)
@@ -12,20 +12,20 @@ add_library(timestamp OBJECT
1212
${timestamp_SOURCE_DIR}/timestamp_tm.c
1313
${timestamp_SOURCE_DIR}/timestamp_valid.c
1414
${timestamp_SOURCE_DIR}/timestamp_parse.c
15-
)
15+
)
1616

1717
if (BUILD_SHARED_LIBS)
1818
set_target_properties(timestamp PROPERTIES
1919
POSITION_INDEPENDENT_CODE 1
2020
C_VISIBILITY_PRESET hidden
21-
)
21+
)
2222
endif ()
2323

2424
target_include_directories(timestamp PUBLIC
2525
$<BUILD_INTERFACE:${timestamp_SOURCE_DIR}>
2626
$<INSTALL_INTERFACE:include/timestamp>
27-
)
27+
)
2828
install(
2929
TARGETS timestamp
30-
EXPORT ${PROJECT_NAME}-targets
30+
EXPORT ${LD_TARGETS_EXPORT_NAME}
3131
)

0 commit comments

Comments
 (0)