libcpr / cpr

C++ Requests: Curl for People, a spiritual port of Python Requests.
https://docs.libcpr.org/
Other
6.29k stars 903 forks source link

Built-in curl link to libssh2 automatically #1001

Closed Ace-Radom closed 6 months ago

Ace-Radom commented 6 months ago

Description

Hey there: I use libcpr in one of my project and I'm troubled with the following problems: the build on my computer works pretty fine, but the build from github workflows cannot run on my computer: it says libssh2-1__.dll and zlib1__.dll are not found.

Here is the cpr settings I use in my CMakeLists:

set(CPR_ENABLE_CURL_HTTP_ONLY ON)
set(CPR_ENABLE_SSL ON)
set(CPR_FORCE_OPENSSL_BACKEND ON)
set(CURL_ZLIB OFF CACHE STRING "" FORCE)

Later I figured out that ssh library doesn't exist in all env PATH on my computer, therefore cpr configure outputed:

...
-- Could NOT find LibSSH2 (missing: LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR)
...

but on github workflows it is found under strawberry perl libs:

...
-- Found LibSSH2: C:/Strawberry/c/lib/libssh2.a (found version "1.8.2") 
...

and it leads to a 'chain' dependency problem because: libssh itself uses a openssl library with a different filename (and different build-cfgs maybe), and it also relies on zlib.

I got the detailed dependencies of libcurl-d.dll which is built by github workflows, and libssh2-1__.dll which is got from github action servers with dumpbin tool provided by vs.

Dump of file libcurl-d.dll  // github workflows, debug build, mingw 12.2.0

File Type: DLL

  Image has the following dependencies:

    bcrypt.dll
    CRYPT32.dll
    KERNEL32.dll
    api-ms-win-crt-convert-l1-1-0.dll
    api-ms-win-crt-environment-l1-1-0.dll
    api-ms-win-crt-filesystem-l1-1-0.dll
    api-ms-win-crt-heap-l1-1-0.dll
    api-ms-win-crt-math-l1-1-0.dll
    api-ms-win-crt-private-l1-1-0.dll
    api-ms-win-crt-runtime-l1-1-0.dll
    api-ms-win-crt-stdio-l1-1-0.dll
    api-ms-win-crt-string-l1-1-0.dll
    api-ms-win-crt-time-l1-1-0.dll
    api-ms-win-crt-utility-l1-1-0.dll
    WS2_32.dll
    libcrypto-1_1-x64.dll
    libssl-1_1-x64.dll
    libssh2-1__.dll

=====================

Dump of file libssh2-1__.dll

File Type: DLL

  Image has the following dependencies:

    libcrypto-1_1-x64__.dll
    zlib1__.dll
    KERNEL32.dll
    msvcrt.dll
    USER32.dll
    WS2_32.dll

And this is the curl lib built on my computer:

Dump of file libcurl-d.dll  // local build, release build, mingw 13.1.0

File Type: DLL

  Image has the following dependencies:

    bcrypt.dll
    CRYPT32.dll
    KERNEL32.dll
    msvcrt.dll
    WS2_32.dll
    libcrypto-1_1-x64.dll
    libssl-1_1-x64.dll

Is there a way to disable the link to ssh library (like disabling zlib)? Because it's unnecessary in my project and the dependencies cause really big problems on development.

Example/How to Reproduce

  1. Install strawberry perl (or other things contain a libssh2 lib) and add it to PATH
  2. Configure CMake and build
  3. Install build results to test VMs (with absolute no C/C++ runtime and other libs)
  4. Cannot find libssh2-1__.dll

Possible Fix

No response

Where did you get it from?

GitHub (branch e.g. master)

Additional Context/Your Environment

COM8 commented 6 months ago

@Ace-Radom Thanks for taking the time to write such a detailed issue!

Do you need to compile your code as a shared executable BUILD_SHARED_LIBS=OFF?

Or does your use case allow for a static executable (BUILD_SHARED_LIBS=ON)?

Ace-Radom commented 6 months ago

Do you need to compile your code as a shared executable BUILD_SHARED_LIBS=OFF?

Or does your use case allow for a static executable (BUILD_SHARED_LIBS=ON)?

I'm not quite sure what do shared & static executable mean, but I set BUILD_SHARED_LIBS variable as ON in my project. But building cpr as a static lib is also allowed.

And btw, the problem with libssh is, not all of us (the developers) have this library on their working computer, and the link to this thing is kinda...an accident. This causes inconsistency in the develop environments, because some of the builds are linked to libssh2-1__.dll but some of them aren't. I want to disable the link to libssl because it seems that all things work fine without it, and it's always better to have less dependencies.

And also thx for the quick response xD

COM8 commented 6 months ago

A bit of context:

Other things you might want to look into is packaging. Or especially cpack and letting it export everything related as a single ZIP file. Then after extracting you can directly start executing since all libs are present.

To solve issues on Windows where not all libs are located inside the build directory, take a look at this example: https://github.com/libcpr/example-cmake-fetch-content/blob/d99dfed29be9e1e3e9100b5b5abd714f701f7fbe/CMakeLists.txt#L25-L28

Ace-Radom commented 6 months ago

I digged into the CMakeLists in built-in curl and found the following codes:

#libSSH2
option(CURL_USE_LIBSSH2 "Use libSSH2" ON)
mark_as_advanced(CURL_USE_LIBSSH2)
set(USE_LIBSSH2 OFF)

if(CURL_USE_LIBSSH2)
  find_package(LibSSH2)
  if(LIBSSH2_FOUND)
    list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY})
    list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}")
    include_directories("${LIBSSH2_INCLUDE_DIR}")
    set(USE_LIBSSH2 ON)
  endif()
endif()

# libssh
option(CURL_USE_LIBSSH "Use libSSH" OFF)
mark_as_advanced(CURL_USE_LIBSSH)
if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH)
  find_package(libssh CONFIG)
  if(libssh_FOUND)
    message(STATUS "Found libssh ${libssh_VERSION}")
    # Use imported target for include and library paths.
    list(APPEND CURL_LIBS ssh)
    set(USE_LIBSSH ON)
  endif()
endif()

I found the location of this code in the curl repo here.

And therefore I added this two lines in my CMakeLists:

set(CURL_USE_LIBSSH2 OFF CACHE STRING "" FORCE)
set(CURL_USE_LIBSSH OFF CACHE STRING "" FORCE)

and after that cpr doesn't search for libssh anymore.

I'm testing it on my github workflows but I think it'll work.

Ace-Radom commented 6 months ago

A bit of context:

  • BUILD_SHARED_LIBS=ON - builds the executable an libraries into separate files that get linked during application startup. Benefit: If multiple applications need the same lib, they share disk space and RAM.
  • BUILD_SHARED_LIBS=OFF - builds the executable and libraries into a single executable (file). Benefits: Single executable that might be a bit larger.

Other things you might want to look into is packaging. Or especially cpack and letting it export everything related as a single ZIP file. Then after extracting you can directly start executing since all libs are present.

To solve issues on Windows where not all libs are located inside the build directory, take a look at this example: https://github.com/libcpr/example-cmake-fetch-content/blob/d99dfed29be9e1e3e9100b5b5abd714f701f7fbe/CMakeLists.txt#L25-L28

I see...I'll also pay attention to it.

COM8 commented 6 months ago

I'm testing it on my github workflows but I think it'll work.

Let me know what comes out of it and if there are any side effects with it.

Ace-Radom commented 6 months ago

Oh yes it worked, curl doesn't search for libssh after setting these two variables anymore. And surely, it is not linked to libssh2-1__.dll

Let me know what comes out of it and if there are any side effects with it.

I didn't find any side effects up till now but I must say I didn't cover all situations. I'm only sure for one thing that CURL_USE_LIBSSH2=OFF does ignore libssh and the built-in curl can also be built without it, but I'm not sure if it will also disable some functions in curl and what will be disabled.

COM8 commented 6 months ago

Perfect! Thanks for the feedback. Closing this one as complete.