Skip to content

Commit

Permalink
feat: preliminary find_package support
Browse files Browse the repository at this point in the history
  • Loading branch information
cwaldren-ld committed Oct 7, 2024
1 parent 18b9cfd commit 6818481
Show file tree
Hide file tree
Showing 24 changed files with 277 additions and 101 deletions.
10 changes: 9 additions & 1 deletion .github/actions/cmake-test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ inputs:
description: 'Boost toolset'
required: false


runs:
using: composite
steps:
Expand All @@ -36,6 +35,15 @@ runs:
# along in the same manner to those test projects via the command line.
BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }}
OPENSSL_ROOT_DIR: ${{ steps.install-openssl.outputs.OPENSSL_ROOT_DIR }}
CMAKE_INSTALL_PREFIX: ../LAUNCHDARKLY_INSTALL
- name: Build the SDK
shell: bash
run: |
cmake --build build
- name: Install the SDK
shell: bash
run: |
cmake --install build
- name: Run CMake Integration Tests
shell: bash
run: |
Expand Down
47 changes: 43 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.19)
include(CMakeDependentOption)

project(
LaunchDarklyCPPSDKs
launchdarkly
VERSION 0.1
DESCRIPTION "LaunchDarkly C++ SDK Monorepo (Server/Client)"
LANGUAGES CXX C
Expand All @@ -21,8 +21,6 @@ if (POLICY CMP0144)
cmake_policy(SET CMP0144 NEW)
endif ()

include(GNUInstallDirs)

option(BUILD_TESTING "Top-level switch for testing. Turn off to disable unit and contract tests." ON)

option(LD_BUILD_SHARED_LIBS "Build the SDKs as shared libraries" OFF)
Expand Down Expand Up @@ -155,12 +153,20 @@ endif ()

set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)

if (POLICY CMP0167)
# TODO: Update to use the Boost project's cmake config directly, since FindBoost was deprecated in
# cmake >= 3.30.
cmake_policy(SET CMP0167 OLD)
endif ()

find_package(Boost 1.81 REQUIRED COMPONENTS json url coroutine)
message(STATUS "LaunchDarkly: using Boost v${Boost_VERSION}")

include(${CMAKE_FILES}/certify.cmake)
set(FOXY_BUILD_TESTING OFF)
add_subdirectory(vendor/foxy)


# Common, internal, and server-sent-events are built as "object" libraries.
add_subdirectory(libs/common)
add_subdirectory(libs/internal)
Expand All @@ -185,3 +191,36 @@ if (LD_BUILD_EXAMPLES)
message(STATUS "LaunchDarkly: building examples")
add_subdirectory(examples)
endif ()


# Support installation of a cmake package.
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/launchdarklyConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
)

install(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/launchdarklyConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/launchdarklyConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/launchdarkly"
)

configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/launchdarkly.pc.in
${CMAKE_CURRENT_BINARY_DIR}/launchdarkly.pc
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/launchdarkly.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)


install(
EXPORT launchdarklyTargets
NAMESPACE launchdarkly::
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/launchdarkly"
)
51 changes: 40 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ GoogleTest is used for testing.

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

## CMake Usage
## CMake Options

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

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

**Note:** _if building the SDKs as shared libraries, then unit tests won't be able to link correctly since the SDK's C++
symbols aren't exposed. To run unit tests, build a static library._

> [!WARNING]
> When building shared libraries C++ symbols are not exported, only the C API will be exported. This is because C++ does
> not have a stable ABI.
> not have a stable ABI. For this reason, the SDK's unit tests are not built in shared library mode.
## Building the SDK from Source

Basic usage example:
To configure the SDK's CMake project:

```bash
mkdir -p build && cd build
cmake -G"Unix Makefiles" ..
# Use 'make' as the build system.
cmake -B build -S . -G"Unix Makefiles"
```

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

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

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

## Incorporating the SDK via `add_subdirectory`

The SDK can be incorporated into an existing application using CMake via `add_subdirectory.`.

```cmake
# Set SDK build options, for example:
set(LD_BUILD_SHARED_LIBS On)
add_subdirectory(path-to-cpp-sdks-repo)
target_link_libraries(your-app PRIVATE launchdarkly::client)
# ... or launchdarkly::server
````
## Incorporating the SDK via `find_package`
> [!WARNING]
> Preliminary support for `find_package` is available. The package configuration is subject to change, do not expect it
> to be stable as long as this notice is present.
If you've installed the SDK on the build system via `cmake --install`, you can consume it from
the target application like so:
```cmake
find_package(launchdarkly REQUIRED)
target_link_libraries(your-app PRIVATE launchdarkly::launchdarkly-cpp-client)
# ... or launchdarkly::launchdarkly-cpp-server
```

## LaunchDarkly overview

[LaunchDarkly](https://www.launchdarkly.com) is a feature management platform that serves trillions of feature flags
Expand Down
1 change: 1 addition & 0 deletions cmake-tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
include(declareProjectTest.cmake)
add_subdirectory(test_find_package)
add_subdirectory(test_add_subdirectory)
7 changes: 7 additions & 0 deletions cmake-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,10 @@ Additionally, certain variables must be forwarded to each test project CMake con

Checks that a project can include the SDK as a sub-project, via `add_subdirectory`.
This would be a likely use-case when the repo is a submodule of another project.

### cmake_projects/test_find_package

Checks that a project can include the SDK via `find_package(ldserverapi)`.
This would be a likely use-case if the SDK was installed on the system by the user.

**NOTE:** Requires SDK to be installed.
7 changes: 4 additions & 3 deletions cmake-tests/declareProjectTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ macro(declare_find_package_test name)
NAME ${test_prefix}_configure
COMMAND
${CMAKE_COMMAND}
# Since project/CMakeLists.txt uses find_package(), it needs to know where to find
# ldserverapiConfig.cmake. That can be found where the SDK is installed, which is CMAKE_INSTALL_PREFIX.
-DCMAKE_PREFIX_PATH=${CMAKE_INSTALL_PREFIX}
# The project under test is going to use find_package() to find the launchdarkly SDK. The package config
# is going to in turn find_package() for boost. So, we need to pass in the location of the SDK's package
# config file, as well as boost's.
"-DCMAKE_PREFIX_PATH=${CMAKE_INSTALL_PREFIX};${BOOST_ROOT}"
${CMAKE_CURRENT_SOURCE_DIR}/project
)

Expand Down
3 changes: 3 additions & 0 deletions cmake-tests/test_find_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This test assumes that the SDK has been installed at CMAKE_INSTALL_PREFIX.
declare_find_package_test(test_find_package)
add_build_step(test_find_package)
12 changes: 12 additions & 0 deletions cmake-tests/test_find_package/project/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.19)

project(UseFindPackageTest)

find_package(launchdarkly REQUIRED)

add_executable(use_find_package_server main_server.cpp)
target_link_libraries(use_find_package_server launchdarkly::launchdarkly-cpp-server)


add_executable(use_find_package_client main_client.cpp)
target_link_libraries(use_find_package_client launchdarkly::launchdarkly-cpp-client)
25 changes: 25 additions & 0 deletions cmake-tests/test_find_package/project/main_client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <launchdarkly/client_side/client.hpp>
#include <launchdarkly/context_builder.hpp>

#include <cstring>
#include <iostream>

using namespace launchdarkly;
using namespace launchdarkly::client_side;

int main() {
auto config = ConfigBuilder("sdk-key").Build();
if (!config) {
std::cout << "error: config is invalid: " << config.error() << '\n';
return 1;
}

auto context =
ContextBuilder().Kind("user", "example-user-key").Name("Sandy").Build();

auto client = Client(std::move(*config), std::move(context));

client.StartAsync();

std::cout << client.Initialized() << '\n';
}
23 changes: 23 additions & 0 deletions cmake-tests/test_find_package/project/main_server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <launchdarkly/server_side/client.hpp>
#include <launchdarkly/server_side/config/config_builder.hpp>

#include <cstring>
#include <iostream>

using namespace launchdarkly;
using namespace launchdarkly::server_side;

int main() {
auto config = ConfigBuilder("sdk-key").Build();
if (!config) {
std::cout << "error: config is invalid: " << config.error() << '\n';
return 1;
}

auto client = Client(std::move(*config));

client.StartAsync();

std::cout << client.Initialized() << '\n';

}
23 changes: 0 additions & 23 deletions cmake/certify.cmake

This file was deleted.

4 changes: 4 additions & 0 deletions cmake/googletest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ FetchContent_Declare(googletest
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

# Disable installation of googletest
set(INSTALL_GTEST OFF CACHE BOOL "Disable googletest installation" FORCE)

FetchContent_MakeAvailable(googletest)
8 changes: 0 additions & 8 deletions cmake/launchdarkly-cpp-clientConfig.cmake

This file was deleted.

16 changes: 16 additions & 0 deletions cmake/launchdarklyConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
include(CMakeFindDependencyMacro)

if (NOT DEFINED Boost_USE_STATIC_LIBS)
if (LD_DYNAMIC_LINK_BOOST)
set(Boost_USE_STATIC_LIBS OFF)
else ()
set(Boost_USE_STATIC_LIBS ON)
endif ()
endif ()

find_dependency(Boost 1.81 COMPONENTS json url coroutine)
find_dependency(OpenSSL)
find_dependency(tl-expected)
find_dependency(certify)

include(${CMAKE_CURRENT_LIST_DIR}/launchdarklyTargets.cmake)
10 changes: 5 additions & 5 deletions cmake/rfc3339_timestamp.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FetchContent_Declare(timestamp
GIT_REPOSITORY https://github.com/chansen/c-timestamp
GIT_TAG "b205c407ae6680d23d74359ac00444b80989792f"
)
)

FetchContent_GetProperties(timestamp)
if (NOT timestamp_POPULATED)
Expand All @@ -12,20 +12,20 @@ add_library(timestamp OBJECT
${timestamp_SOURCE_DIR}/timestamp_tm.c
${timestamp_SOURCE_DIR}/timestamp_valid.c
${timestamp_SOURCE_DIR}/timestamp_parse.c
)
)

if (BUILD_SHARED_LIBS)
set_target_properties(timestamp PROPERTIES
POSITION_INDEPENDENT_CODE 1
C_VISIBILITY_PRESET hidden
)
)
endif ()

target_include_directories(timestamp PUBLIC
$<BUILD_INTERFACE:${timestamp_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/timestamp>
)
)
install(
TARGETS timestamp
EXPORT ${PROJECT_NAME}-targets
EXPORT ${PROJECT_NAME}Targets
)
Loading

0 comments on commit 6818481

Please sign in to comment.