cmake: fix logic for openssl/zlib binutils ld workaround

While working #16973, the binutils ld lib order workaround logic
regressed so that it modified the wrong target, writing into the system
`ZLIB::ZLIB` and `OpenSSL::Crypto` ones a `INTERFACE_LINK_LIBRARIES`
property, instead of creating CURL-namespaced targets. Oddly enough,
this also fixed the binutils ld lib ordering issue. It seems this
property makes CMake insert each referenced library in two more
positions (not at the very end though), which allows ld to resolve all
symbols in the cases tested in CI.

Fix by creating the indented namespaced targets, and also creating
these in `curl-config.cmake` to be available when consuming libcurl.

Note that the logic continues doing `get_target_property()` on the two
system targets above. If these targets are defined manually and miss
the `LOCATION` propery, or are defined as aliases, this command may
fail. curl expects these targets be created by CMake's `FindZLIB` and
`FindOpenSSL` built-in Find modules (or ones compatible). Ref: #20419

The binutils ld issue is reproduced by these CI jobs:
 - Linux gcc glibc (amd64, arm64)
- Windows gcc zlib-classic (x64)

Currently using this curl-for-win revision:
7d12669daf
Examples:
https://github.com/curl/curl/actions/runs/21332437230/job/61399234023?pr=20427
https://github.com/curl/curl/actions/runs/21332437230/job/61399234033?pr=20427

Comparison of lib orders, as passed by CMake to the linker:

without workaround (possibly breaking binutils `ld`):
```diff
 -framework [...]
 libssl.dylib
 libcrypto.dylib
 libz.tbd
 -lssh2 -lidn2
 libldap.tbd
 liblber.tbd
 -lbrotlidec -lbrotlicommon -lzstd -lnghttp2 -lpsl -lrtmp
 -lz
 -lssl
 -lcrypto
```

before this patch:
```diff
 -framework [...]
 libssl.dylib
 libcrypto.dylib
 libz.tbd
+libcrypto.dylib <== inserted via `INTERFACE_LINK_LIBRARIES`
+libz.tbd        <== inserted via `INTERFACE_LINK_LIBRARIES`
 -lssh2 -lidn2
 libldap.tbd
 liblber.tbd
+libcrypto.dylib <== inserted via `INTERFACE_LINK_LIBRARIES`
+ibz.tbd         <== inserted via `INTERFACE_LINK_LIBRARIES`
 -lbrotlidec -lbrotlicommon -lzstd -lnghttp2 -lpsl -lrtmp
 -lz
 -lssl
 -lcrypto
```

after this patch:
```diff
 -framework [...]
 libssl.dylib
 libcrypto.dylib
 libz.tbd
 -lssh2 -lidn2
 libldap.tbd
 liblber.tbd
 -lbrotlidec -lbrotlicommon -lzstd -lnghttp2 -lpsl -lrtmp
 -lz
 -lssl
 -lcrypto
+libcrypto.dylib <== inserted via `CURL::OpenSSL_Crypto`
+libz.tbd        <== inserted via `CURL::ZLIB`
```

Bug: https://github.com/curl/curl/pull/20382#discussion_r2716660108
Reverts: 615c43eae8
Follow-up to 16f073ef49 #16973

Closes #20427
This commit is contained in:
Viktor Szakats 2026-01-25 13:04:58 +01:00
parent 4516023152
commit 3e841630ec
No known key found for this signature in database
GPG Key ID: B5ABD165E2AEF201
2 changed files with 20 additions and 13 deletions

View File

@ -39,9 +39,19 @@ if("@USE_OPENSSL@")
else()
find_dependency(OpenSSL)
endif()
if(TARGET OpenSSL::Crypto AND NOT TARGET CURL::OpenSSL_Crypto)
add_library(CURL::OpenSSL_Crypto INTERFACE IMPORTED)
get_target_property(_curl_libname OpenSSL::Crypto LOCATION)
set_target_properties(CURL::OpenSSL_Crypto PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
endif()
endif()
if("@HAVE_LIBZ@")
find_dependency(ZLIB "@ZLIB_VERSION_MAJOR@")
if(TARGET ZLIB::ZLIB AND NOT TARGET CURL::ZLIB)
add_library(CURL::ZLIB INTERFACE IMPORTED)
get_target_property(_curl_libname ZLIB::ZLIB LOCATION)
set_target_properties(CURL::ZLIB PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
endif()
endif()
set(_curl_cmake_module_path_save ${CMAKE_MODULE_PATH})

View File

@ -1813,21 +1813,18 @@ endif()
# before dependencies detected via curl's custom Find modules, and breaks
# linkers sensitive to lib order. There must be a better solution to this.
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(_libs "")
if(USE_OPENSSL)
list(APPEND _libs OpenSSL::Crypto)
if(USE_OPENSSL AND TARGET OpenSSL::Crypto)
add_library(CURL::OpenSSL_Crypto INTERFACE IMPORTED)
get_target_property(_curl_libname OpenSSL::Crypto LOCATION)
set_target_properties(CURL::OpenSSL_Crypto PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
list(APPEND CURL_LIBS CURL::OpenSSL_Crypto)
endif()
if(HAVE_LIBZ)
list(APPEND _libs ZLIB::ZLIB)
if(HAVE_LIBZ AND TARGET ZLIB::ZLIB)
add_library(CURL::ZLIB INTERFACE IMPORTED)
get_target_property(_curl_libname ZLIB::ZLIB LOCATION)
set_target_properties(CURL::ZLIB PROPERTIES INTERFACE_LINK_LIBRARIES "${_curl_libname}")
list(APPEND CURL_LIBS CURL::ZLIB)
endif()
foreach(_lib IN LISTS _libs)
if(TARGET "${_lib}")
add_library(CURL::${_lib} INTERFACE IMPORTED)
get_target_property(_libname "${_lib}" LOCATION)
set_target_properties(${_lib} PROPERTIES INTERFACE_LINK_LIBRARIES "${_libname}")
list(APPEND CURL_LIBS ${_lib})
endif()
endforeach()
if(WIN32)
add_library(CURL::win32_winsock INTERFACE IMPORTED)
set_target_properties(CURL::win32_winsock PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32")