Skip to content

Commit f915183

Browse files
committed
build: consume an existing httplib target instead of fetching a second copy
When a consumer has already defined `httplib::httplib`, fastmcpp_core now links it rather than populating its own cpp-httplib checkout and exposing it as a PUBLIC include directory. A binary that also links the consumer's copy was compiling two versions of the same header-only library with different feature macros, so `httplib::ClientImpl` had two layouts under one name -- an ODR violation that presented as a crash inside the client, not a link error. FASTMCPP_ENABLE_OPENSSL no longer stamps CPPHTTPLIB_OPENSSL_SUPPORT over an externally supplied target, whose feature set is the consumer's to decide. Standalone builds are unchanged: with no such target present, fastmcpp fetches cpp-httplib as before. Also adds FASTMCPP_BUILD_CLI (default ON) so an embedding project can skip the command-line executable it does not ship.
1 parent 9a3ee71 commit f915183

1 file changed

Lines changed: 43 additions & 12 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,47 @@ endif()
8787
target_link_libraries(fastmcpp_core PUBLIC nlohmann_json::nlohmann_json)
8888

8989
# Header-only HTTP library (cpp-httplib)
90+
#
91+
# If the surrounding project already provides an httplib::httplib target, CONSUME
92+
# IT. cpp-httplib is header-only, so fetching a second private copy here puts two
93+
# sets of inline definitions into one binary. Whenever the two differ — a
94+
# different version, or different CPPHTTPLIB_*_SUPPORT feature macros — the
95+
# classes have different layouts per translation unit, the linker keeps one weak
96+
# definition, and callers read and write through mismatched offsets. It surfaces
97+
# as a crash inside httplib's own mutexes, not as a link error.
9098
include(FetchContent)
91-
FetchContent_Declare(
92-
cpp_httplib
93-
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
94-
GIT_TAG v0.15.3
95-
)
96-
FetchContent_GetProperties(cpp_httplib)
97-
if(NOT cpp_httplib_POPULATED)
98-
FetchContent_Populate(cpp_httplib)
99+
if(TARGET httplib::httplib)
100+
# Same headers AND same feature macros as every other TU in the final binary.
101+
target_link_libraries(fastmcpp_core PUBLIC httplib::httplib)
102+
set(FASTMCPP_HTTPLIB_EXTERNAL TRUE)
103+
message(STATUS "fastmcpp: using the project-provided httplib::httplib target")
104+
else()
105+
FetchContent_Declare(
106+
cpp_httplib
107+
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
108+
GIT_TAG v0.15.3
109+
)
110+
FetchContent_GetProperties(cpp_httplib)
111+
if(NOT cpp_httplib_POPULATED)
112+
FetchContent_Populate(cpp_httplib)
113+
endif()
114+
target_include_directories(fastmcpp_core PUBLIC ${cpp_httplib_SOURCE_DIR})
115+
set(FASTMCPP_HTTPLIB_EXTERNAL FALSE)
116+
message(STATUS "fastmcpp: fetching a private cpp-httplib (no httplib::httplib target found)")
99117
endif()
100-
target_include_directories(fastmcpp_core PUBLIC ${cpp_httplib_SOURCE_DIR})
101118

102119
# Optional: OpenSSL for HTTPS/SSL support
103120
if(FASTMCPP_ENABLE_OPENSSL)
104121
find_package(OpenSSL REQUIRED)
105-
target_compile_definitions(fastmcpp_core PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
122+
# With an external httplib target, that target decides whether the SSL code
123+
# paths are compiled in. Defining CPPHTTPLIB_OPENSSL_SUPPORT here anyway would
124+
# re-open the very layout skew this block avoids, from the other side.
125+
if(FASTMCPP_HTTPLIB_EXTERNAL)
126+
message(STATUS "FASTMCPP_ENABLE_OPENSSL=ON: deferring CPPHTTPLIB_OPENSSL_SUPPORT "
127+
"to the project-provided httplib::httplib target")
128+
else()
129+
target_compile_definitions(fastmcpp_core PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
130+
endif()
106131
target_link_libraries(fastmcpp_core PUBLIC OpenSSL::SSL OpenSSL::Crypto)
107132
message(STATUS "FASTMCPP_ENABLE_OPENSSL=ON: HTTPS/SSL support enabled")
108133
else()
@@ -186,8 +211,14 @@ target_sources(fastmcpp_core PRIVATE src/internal/process.cpp)
186211
find_package(Threads REQUIRED)
187212
target_link_libraries(fastmcpp_core PRIVATE Threads::Threads)
188213

189-
add_executable(fastmcpp src/cli/main.cpp)
190-
target_link_libraries(fastmcpp PRIVATE fastmcpp_core)
214+
# Embedders link fastmcpp_core and never invoke this CLI, but it was unconditional, so
215+
# every consumer compiled and linked it on every build. Default ON keeps standalone
216+
# fastmcpp unchanged; embedders turn it off next to FASTMCPP_BUILD_TESTS/EXAMPLES.
217+
option(FASTMCPP_BUILD_CLI "Build the fastmcpp command-line executable" ON)
218+
if(FASTMCPP_BUILD_CLI)
219+
add_executable(fastmcpp src/cli/main.cpp)
220+
target_link_libraries(fastmcpp PRIVATE fastmcpp_core)
221+
endif()
191222

192223
if(FASTMCPP_BUILD_TESTS)
193224
enable_testing()

0 commit comments

Comments
 (0)