Skip to content

Commit 6818481

Browse files
committed
feat: preliminary find_package support
1 parent 18b9cfd commit 6818481

File tree

24 files changed

+277
-101
lines changed

24 files changed

+277
-101
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: 43 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)
@@ -155,12 +153,20 @@ endif ()
155153

156154
set(Boost_USE_MULTITHREADED ON)
157155
set(Boost_USE_STATIC_RUNTIME OFF)
156+
157+
if (POLICY CMP0167)
158+
# TODO: Update to use the Boost project's cmake config directly, since FindBoost was deprecated in
159+
# cmake >= 3.30.
160+
cmake_policy(SET CMP0167 OLD)
161+
endif ()
162+
158163
find_package(Boost 1.81 REQUIRED COMPONENTS json url coroutine)
159164
message(STATUS "LaunchDarkly: using Boost v${Boost_VERSION}")
160165

161-
include(${CMAKE_FILES}/certify.cmake)
166+
set(FOXY_BUILD_TESTING OFF)
162167
add_subdirectory(vendor/foxy)
163168

169+
164170
# Common, internal, and server-sent-events are built as "object" libraries.
165171
add_subdirectory(libs/common)
166172
add_subdirectory(libs/internal)
@@ -185,3 +191,36 @@ if (LD_BUILD_EXAMPLES)
185191
message(STATUS "LaunchDarkly: building examples")
186192
add_subdirectory(examples)
187193
endif ()
194+
195+
196+
# Support installation of a cmake package.
197+
include(CMakePackageConfigHelpers)
198+
include(GNUInstallDirs)
199+
200+
write_basic_package_version_file(
201+
"${CMAKE_CURRENT_BINARY_DIR}/launchdarklyConfigVersion.cmake"
202+
COMPATIBILITY SameMajorVersion
203+
)
204+
205+
install(FILES
206+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/launchdarklyConfig.cmake"
207+
"${CMAKE_CURRENT_BINARY_DIR}/launchdarklyConfigVersion.cmake"
208+
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/launchdarkly"
209+
)
210+
211+
configure_file(
212+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/launchdarkly.pc.in
213+
${CMAKE_CURRENT_BINARY_DIR}/launchdarkly.pc
214+
)
215+
216+
install(
217+
FILES ${CMAKE_CURRENT_BINARY_DIR}/launchdarkly.pc
218+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
219+
)
220+
221+
222+
install(
223+
EXPORT launchdarklyTargets
224+
NAMESPACE launchdarkly::
225+
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/launchdarkly"
226+
)

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 ${PROJECT_NAME}Targets
3131
)

0 commit comments

Comments
 (0)