Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to statically link with CPM #1137

Open
Sightem opened this issue Nov 9, 2024 · 2 comments
Open

Unable to statically link with CPM #1137

Sightem opened this issue Nov 9, 2024 · 2 comments

Comments

@Sightem
Copy link

Sightem commented Nov 9, 2024

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
@COM8
Copy link
Member

COM8 commented Nov 9, 2024

@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.

@Sightem
Copy link
Author

Sightem commented Nov 11, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants