Unable to statically link with CPM
Description
It appears that the library has trouble with static linking (specifically in debug mode) when included using CPM.
I cannot reproduce this when building in release or release with debug info modes.
This problem appears to have been caused by a change in v1.11.0, as I cannot reproduce this using v1.9.8
[1/2] Building CXX object CMakeFiles/cpr_static_repro.dir/src/main.cpp.obj
[2/2] Linking CXX executable cpr_static_repro.exe
FAILED: cpr_static_repro.exe
cmd.exe /C "cd . && C:\msys64\mingw64\bin\c++.exe -g -static -static-libgcc -static-libstdc++ CMakeFiles/cpr_static_repro.dir/src/main.cpp.obj -o cpr_static_repro.exe -Wl,--out-implib,libcpr_static_repro.dll.a -Wl,--major-image-version,0,--minor-image-version,0 _deps/cpr-build/cpr/libcpr.a _deps/curl-build/lib/libcurl-d.a C:/msys64/mingw64/lib/libidn2.dll.a -lws2_32 -lbcrypt C:/msys64/mingw64/lib/libz.dll.a C:/msys64/mingw64/lib/libpsl.dll.a C:/msys64/mingw64/lib/libssh2.dll.a -ladvapi32 -lcrypt32 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/14.2.0/../../../../lib\libstdc++.a(tinfo.o):(.text$_ZNKSt9type_infoeqERKS_+0x0): multiple definition of `std::type_info::operator==(std::type_info const&) const'; _deps/cpr-build/cpr/libcpr.a(session.cpp.obj):C:/msys64/mingw64/include/c++/14.2.0/typeinfo:193: first defined here
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
Example/How to Reproduce
// Directory structure:
//
// minimal-repro/
// ├── CMakeLists.txt
// ├── cmake/
// │ └── CPM.cmake
// └── src/
// └── main.cpp
# CMakeLists.txt
cmake_minimum_required(VERSION 3.26)
project(cpr_static_repro)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
include(cmake/CPM.cmake)
CPMAddPackage(
NAME cpr
GITHUB_REPOSITORY libcpr/cpr
GIT_TAG bb01c8db702fb41e5497aee9c0559ddf4bf13749
OPTIONS
"BUILD_SHARED_LIBS OFF"
"CPR_FORCE_USE_SYSTEM_CURL OFF"
"CPR_BUILD_TESTS OFF"
"CPR_ENABLE_SSL ON"
)
add_executable(cpr_static_repro src/main.cpp)
target_link_options(cpr_static_repro PRIVATE -static -static-libgcc -static-libstdc++)
target_link_libraries(cpr_static_repro PRIVATE cpr::cpr)
// src/main.cpp
#include <cpr/cpr.h>
#include <iostream>
int main() {
auto r = cpr::Get(cpr::Url{"https://api.github.com/repos/libcpr/cpr"});
std::cout << "Status code: " << r.status_code << std::endl;
return 0;
}
// To reproduce:
// 1. Create the directory structure above
// 2. Download CPM.cmake from https://github.com/cpm-cmake/CPM.cmake/releases
// 3. Run:
// mkdir build
// cd build
// cmake -DCMAKE_BUILD_TYPE=Debug ..
// cmake --build . --config Debug
Possible Fix
No response
Where did you get it from?
Other (specify in "Additional Context/Your Environment")
Additional Context/Your Environment
- OS: Windows 10 22H2
- Version: 1.11.0
- Package Manager: CPM
@Sightem thanks for reporting!
When I try building both 1.11.0 and 1.9.8 with the following CMake config based on yours
cmake_minimum_required(VERSION 3.20)
project(cpr_example)
set(CMAKE_CXX_STANDARD 17)
# Set to C++ 11 if you are using cpr <= 1.9.x
# More: https://github.com/libcpr/cpr#supported-releases
# set(CMAKE_CXX_STANDARD 11)
# Set a default build type if none was specified
# Based on: https://github.com/openchemistry/tomviz/blob/master/cmake/BuildType.cmake
set(DEFAULT_BUILD_TYPE "Release")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(DEFAULT_BUILD_TYPE "Debug")
endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.")
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
add_executable(cpr_example main.cpp)
if(WIN32) # Install dlls in the same directory as the executable on Windows
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
endif()
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE)
set(CPR_FORCE_USE_SYSTEM_CURL OFF CACHE INTERNAL "" FORCE)
set(CPR_BUILD_TESTS OFF CACHE INTERNAL "" FORCE)
set(CPR_ENABLE_SSL OFF CACHE INTERNAL "" FORCE)
set(CURL_ZLIB OFF CACHE INTERNAL "" FORCE)
target_link_options(cpr_example PUBLIC -static -static-libgcc -static-libstdc++)
include(FetchContent)
FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git
GIT_TAG 1.11.0)
FetchContent_MakeAvailable(cpr)
target_link_libraries(cpr_example PRIVATE cpr::cpr)
I run into a different problem:
[build] [29/31 90% :: 4.080] Building CXX object _deps/cpr-build/cpr/CMakeFiles/cpr.dir/multiperform.cpp.o
[build] [29/31 93% :: 5.592] Building CXX object _deps/cpr-build/cpr/CMakeFiles/cpr.dir/session.cpp.o
[build] [30/31 96% :: 5.626] Linking CXX static library _deps/cpr-build/cpr/libcpr.a
[build] [31/31 100% :: 5.633] Linking CXX executable cpr_example
[build] FAILED: cpr_example
[build] : && /usr/lib64/ccache/g++ -O3 -DNDEBUG -static -static-libgcc -static-libstdc++ CMakeFiles/cpr_example.dir/main.cpp.o -o cpr_example _deps/cpr-build/cpr/libcpr.a /usr/lib64/libcurl.so && :
[build] /usr/bin/ld: attempted static link of dynamic object `/usr/lib64/libcurl.so'
[build] collect2: error: ld returned 1 exit status
If I remove the -static flag it works, but the executable links against some shared stuff.
ldd build/cpr_example
linux-vdso.so.1 (0x00007ff8e9ca2000)
libnghttp2.so.14 => /lib64/libnghttp2.so.14 (0x00007ff8e9c55000)
libpsl.so.5 => /lib64/libpsl.so.5 (0x00007ff8e9c40000)
libm.so.6 => /lib64/libm.so.6 (0x00007ff8e9b5c000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff8e996b000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff8e9ca4000)
libunistring.so.5 => /lib64/libunistring.so.5 (0x00007ff8e97be000)
libidn2.so.0 => /lib64/libidn2.so.0 (0x00007ff8e979a000)
I suspect curl linkage is not purely static and relies on some shared dependencies that can be build and then used.
Oddly enough, from my own example I get these results. This is with the -static flag still included.
$ ldd C:\\Users\\Sightem\\CLionProjects\\minimal-repro\\cmake-build-debug\\cpr_static_repro.exe
ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ff8b9fb0000)
KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ff8b93e0000)
KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ff8b7790000)
ADVAPI32.dll => /c/WINDOWS/System32/ADVAPI32.dll (0x7ff8b9e30000)
msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7ff8b8ba0000)
sechost.dll => /c/WINDOWS/System32/sechost.dll (0x7ff8b92e0000)
RPCRT4.dll => /c/WINDOWS/System32/RPCRT4.dll (0x7ff8b8a70000)
bcrypt.dll => /c/WINDOWS/System32/bcrypt.dll (0x7ff8b7c90000)
CRYPT32.dll => /c/WINDOWS/System32/CRYPT32.dll (0x7ff8b7b30000)
ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7ff8b7cc0000)
WS2_32.dll => /c/WINDOWS/System32/WS2_32.dll (0x7ff8b9dc0000)
libidn2-0.dll => not found
libpsl-5.dll => not found
libssh2-1.dll => not found
zlib1.dll => not found
Below is the output without the -static flag:
$ ldd C:\\Users\\Sightem\\CLionProjects\\minimal-repro\\cmake-build-debug\\cpr_static_repro.exe
ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ff8b9fb0000)
KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ff8b93e0000)
KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ff8b7790000)
ADVAPI32.dll => /c/WINDOWS/System32/ADVAPI32.dll (0x7ff8b9e30000)
msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7ff8b8ba0000)
sechost.dll => /c/WINDOWS/System32/sechost.dll (0x7ff8b92e0000)
RPCRT4.dll => /c/WINDOWS/System32/RPCRT4.dll (0x7ff8b8a70000)
bcrypt.dll => /c/WINDOWS/System32/bcrypt.dll (0x7ff8b7c90000)
CRYPT32.dll => /c/WINDOWS/System32/CRYPT32.dll (0x7ff8b7b30000)
ucrtbase.dll => /c/WINDOWS/System32/ucrtbase.dll (0x7ff8b7cc0000)
WS2_32.dll => /c/WINDOWS/System32/WS2_32.dll (0x7ff8b9dc0000)
libwinpthread-1.dll => /home/Sightem/libwinpthread-1.dll (0x75c50000)
libidn2-0.dll => not found
libpsl-5.dll => not found
libssh2-1.dll => not found
zlib1.dll => not found
Even weirder, your example works perfectly somehow with no linking errors, Though ldd still yields some strange results:
$ ldd C:\\Users\\Sightem\\CLionProjects\\minimal-repro\\cmake-build-debug\\cpr_example.exe
ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7ff8b9fb0000)
KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7ff8b93e0000)
KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7ff8b7790000)
ADVAPI32.dll => /c/WINDOWS/System32/ADVAPI32.dll (0x7ff8b9e30000)
msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7ff8b8ba0000)
sechost.dll => /c/WINDOWS/System32/sechost.dll (0x7ff8b92e0000)
RPCRT4.dll => /c/WINDOWS/System32/RPCRT4.dll (0x7ff8b8a70000)
bcrypt.dll => /c/WINDOWS/System32/bcrypt.dll (0x7ff8b7c90000)
WS2_32.dll => /c/WINDOWS/System32/WS2_32.dll (0x7ff8b9dc0000)
libidn2-0.dll => not found
libpsl-5.dll => not found
libssh2-1.dll => not found
Going back to the example you provided, it appears that setting CMAKE_CXX_STANDARD to 23 makes the build break. 20 and 17 apparently build and execute just fine (ldd still shows some strange results). I can verify that this happens with CPM too so clearly that is not the issue here.
I cannot seem to reproduce the exact problem you are having however
Hi, Seems like I'm having the same issue. While trying to link CPR statically, the following DLLs are missing at run time (and I'd like to have those libs linked statically):
- libwinpthread-1.dll
- libidn2-0.dll
- libpsl-5.dll
- libssh2-1.dll Is it even possible to make a build without any non-standard (i.e. present in Windows) DLL dependencies?
I might have the same issue but for some reason it just puts the dll files beside the file instead of linking them however i explicitly set the linker and cmake flags to link