Skip to content

[GOLDEN SOLUTION] Add CMake MbedTLS Component Support with Fail-to-Pass Integration Tests#2375

Closed
Teja3804 wants to merge 2 commits intoyhirose:masterfrom
Teja3804:golden-solution
Closed

[GOLDEN SOLUTION] Add CMake MbedTLS Component Support with Fail-to-Pass Integration Tests#2375
Teja3804 wants to merge 2 commits intoyhirose:masterfrom
Teja3804:golden-solution

Conversation

@Teja3804
Copy link

@Teja3804 Teja3804 commented Feb 22, 2026

Solution Approach

I used the existing solution idea from PR #2360 ([CMake] New compoment MbedTLS) and implemented a production-ready version on top of current main with one [sol] commit.

Changes in the [sol] commit:

  • Added CMake options:
    • HTTPLIB_REQUIRE_MBEDTLS
    • HTTPLIB_USE_MBEDTLS_IF_AVAILABLE
  • Added OpenSSL/MbedTLS mutual-exclusion guards to prevent invalid dual-backend configuration.
  • Added MbedTLS discovery path in CMakeLists.txt:
    • find_package(MbedTLS REQUIRED/QUIET)
    • HTTPLIB_IS_USING_MBEDTLS state handling
  • Added MbedTLS wiring to the exported target:
    • Link MbedTLS::mbedtls
    • Export CPPHTTPLIB_MBEDTLS_SUPPORT
  • Added package-config support in cmake/httplibConfig.cmake.in:
    • HTTPLIB_IS_USING_MBEDTLS
    • find_dependency(MbedTLS)
    • httplib_MbedTLS_FOUND
  • Added cmake/FindMbedTLS.cmake and installed it with package config so component discovery works even when MbedTLSConfig.cmake is not provided by the distro.
Screenshot 2026-02-21 180054 Screenshot 2026-02-21 180124 Screenshot 2026-02-21 180219

Testing Approach

I added one fail-to-pass integration test script in the [f2p] commit:

  • test/cmake_mbedtls_component_test.sh

What it validates:

  • Configures and installs httplib with -DHTTPLIB_REQUIRE_MBEDTLS=ON.
  • Builds a consumer project that uses find_package(httplib REQUIRED COMPONENTS MbedTLS) and links httplib::httplib.
  • Verifies exported component state (HTTPLIB_IS_USING_MBEDTLS, httplib_MbedTLS_FOUND).
  • Verifies config must fail when both OpenSSL and MbedTLS auto options are enabled together.

I also updated run_tests.sh to:

  • Install required packages for this test (cmake, ninja-build, libmbedtls-dev, etc.).
  • Dispatch test/cmake_mbedtls_component_test.sh from the comma-separated file argument.

Test Execution Steps

  1. Start clean Docker container using:
    • docker.io/ccrawford4/python-base-amd64:v1.0.9
  2. Clone repo and checkout BASE_COMMIT.
  3. Create run_script.sh from TEST_COMMIT:run_tests.sh.
  4. Run pass-to-pass tests on base commit (pass expected).
  5. Apply [f2p] patch.
  6. Run fail-to-pass tests on base + tests (fail expected).
  7. Apply [sol] patch.
  8. Re-run pass-to-pass and fail-to-pass (both pass expected).

Test Execution + Results

# From inside container

# variables
export PASS_TO_PASS_FILES="$(pwd)/test/test_thread_pool.cc,$(pwd)/test/test_websocket_heartbeat.cc"
export FAIL_TO_PASS_FILES="$(pwd)/test/cmake_mbedtls_component_test.sh"

# base commit
git checkout $BASE_COMMIT

# create run script from test commit
git show $TEST_COMMIT:run_tests.sh > run_script.sh
chmod +x run_script.sh

# pass-to-pass on base (PASS)
bash run_script.sh "$PASS_TO_PASS_FILES"

# apply f2p tests
git show $TEST_COMMIT > test.patch
git apply test.patch

# fail-to-pass on base+tests (FAIL expected)
bash run_script.sh "$FAIL_TO_PASS_FILES"

# apply golden solution
git show $GOLDEN_COMMIT > golden.patch
git apply golden.patch

# pass-to-pass after solution (PASS)
bash run_script.sh "$PASS_TO_PASS_FILES"

# fail-to-pass after solution (PASS)
bash run_script.sh "$FAIL_TO_PASS_FILES"


Fail-to-Pass Tests
test/cmake_mbedtls_component_test.sh

Pass-to-Pass Tests
test/test_thread_pool.cc,test/test_websocket_heartbeat.cc

Fail To Pass Hash
b024ebf0683f4798e060c9ac096309b7afea239d

Solution Hash
db1b1124c4f4766f4ba20fd3dcdac5ff12b72025

Optimal LLM Prompt For a Junior Developer
You are working in cpp-httplib. Add CMake component support for MbedTLS so consumers can do:
find_package(httplib REQUIRED COMPONENTS MbedTLS)

Requirements:
1) Add options in CMakeLists.txt:
   - HTTPLIB_REQUIRE_MBEDTLS (default OFF)
   - HTTPLIB_USE_MBEDTLS_IF_AVAILABLE (default OFF)
2) Ensure OpenSSL and MbedTLS backends are mutually exclusive at configure time.
3) Add MbedTLS discovery and state propagation:
   - HTTPLIB_IS_USING_MBEDTLS
4) When MbedTLS is enabled:
   - link MbedTLS::mbedtls
   - add CPPHTTPLIB_MBEDTLS_SUPPORT compile definition
5) Update cmake/httplibConfig.cmake.in to export and resolve MbedTLS dependency and set httplib_MbedTLS_FOUND.
6) Add/ship a FindMbedTLS.cmake fallback so this works on systems without MbedTLSConfig.cmake.
7) Add an integration test that:
   - builds + installs producer with REQUIRE_MBEDTLS=ON
   - builds a consumer using find_package(httplib COMPONENTS MbedTLS)
   - verifies both-backend conflict (OpenSSL + MbedTLS enabled together) fails as expected.
8) Keep commits split:
   - [sol] feature code only
   - [f2p] tests and run script updates



Hints
- Put custom find modules in CMAKE_MODULE_PATH before calling find_package(MbedTLS).
- Install FindMbedTLS.cmake alongside httplibConfig.cmake so downstream find_dependency(MbedTLS) works.
- Prefer integration-level test coverage for CMake component behavior.
- Use a temporary producer/consumer project in the test script to validate real package consumption.

@Spixmaster
Copy link

Spixmaster commented Feb 22, 2026

While I completly neglected the tests, I dislike the ideas of tests for CMake in general and the approach of programming a "...Config.cmake.in" for a dependency in case that the system does not provide it.

For the tests, I do not like Docker. I assume the tests cover one possible environment. What about linkage? Static and shared builds? Every combination of build options? Even different operating systems, Windows, GNU/Linux, Mac? I would not test CMake. That is my opinion.

The tests are just a side note but the main contribution of this pull request is the individual "...Config.cmake.in" for MbedTLS.

The project itself (MbedTLS) should provide its exported CMake target and does so. Imagine every consuming project wrote its own "...Config.cmake.in" for every dependency. That would result in different behaviours all over the place. Despite that, the burden of maintenance increases a lot. I am aware that Brotli has its own "...Config.cmake.in" but Brotli does not provide it itself but a pkgconfig. Even there I would propose using https://cmake.org/cmake/help/latest/module/FindPkgConfig.html to decrease the maintenance.

Being consistent with your approach would require every dependency to have its own "...Config.cmake.in".

I would even support the idea of removing HTTPLIB_USE_XXX_IF_AVAILABLE as brought up in #2360 (comment).

Summary, I do not like complicating CMake more than necessary because CMake itself is annoying at developing and maintaining. Moreover, leave the responsibility of the exported targets at the origin source.

@@ -0,0 +1,79 @@
# A lightweight find module for Mbed TLS that works with older CMake versions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is this better than pkg-config?

@Teja3804 Teja3804 closed this Feb 22, 2026
@Teja3804 Teja3804 deleted the golden-solution branch February 22, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants