Libcurl linking on windows

Trying to use curl, link fails on windows. I have created a minimal project to debug the problem

I have conanfile.txt

[requires]
libcurl/8.2.1

[generators]
CMakeDeps
CMakeToolchain

CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(linkCurl VERSION 1.0 LANGUAGES CXX)

find_package(CURL REQUIRED)
include_directories(${libcurl_CURL_libcurl_INCLUDE_DIRS_RELEASE})

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} ${CURL_LIBRARIES})

Build commands:

C:\Users\torsiver\Projects\link_curl>conan install . --output-folder=build --build=missing [Seems to run OK - conan downloads the package]

cd build

C:\Users\torsiver\Projects\link_curl\build>cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release [seems to run OK]

C:\Users\torsiver\Projects\link_curl\build>cmake --build . [causes ERROR: error LNK2019: unresolved external symbol __imp_curl_easy_strerror]

I tried running with -v which shows this link command:

Link:

  C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\Users\torsiver\Projects\link_curl\build\Debug\linkCurl.exe" /INCREMENTAL /ILK:"linkCurl.dir\Debug\linkCurl.ilk" /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:/Users/torsiver/Projects/link_curl/build/Debug/linkCurl.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:/Users/torsiver/Projects/link_curl/build/Debug/linkCurl.lib" /MACHINE:X64  /machine:x64 linkCurl.dir\Debug\main.obj

Seems CMake is not trying to link libcurl?

The project builds OK on linux (wsl2 Ubuntu 22.04.3 with default tools installed from apt)

Is CURL_LIBRARIES set at all? Does it work if you remove the include directory as well and instead link to CURL::libcurl?

I tried dumping all variables with this.

get_cmake_property(_variableNames VARIABLES)
list (SORT _variableNames)
foreach (_variableName ${_variableNames})
    message(STATUS "${_variableName}=${${_variableName}}")
endforeach()

It seems CURL_LIBRARIES is not set. I tried to use CURL::libcurl as shown below (the variable libcurl_LIBRARIES_RELEASE has this value so maybe i should be using this to get windows and linux consistent):

target_link_libraries(${PROJECT_NAME} CURL::libcurl)

This makes no difference (edited because my first conclusion was wrong, caused by an experiment).

It seems Conan has correctly downloaded the curl lib (this file exists after running Conan install: c:\Users\torsiver.conan2\p\libcu75d014a1ff3cb\p\lib\libcurl.lib), but somehow CMake is not picking it up correctly under windows.

CMake uses the correct include path during compile, so find_package must have found the correct curl from Conan

ClCompile:
  C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\CL.exe /c
  /IC:\Users\torsiver\.conan2\p\libcu75d014a1ff3cb\p\include /Zi /nologo /W1 /WX- /diagnostics:column /MP20 /Od /Ob0 /D
   _MBCS /D WIN32 /D _WINDOWS /D "CMAKE_INTDIR=\"Debug\"" /Gm- /EHsc /RTC1 /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope
   /Zc:inline /GR /std:c++14 /Fo"linkCurl.dir\Debug\\" /Fd"linkCurl.dir\Debug\vc142.pdb" /external:W1 /Gd /TP /errorRep
  ort:queue C:\Users\torsiver\Projects\link_curl\src\main.cpp
  main.cpp

It is odd to me that FindCURL would define a target without a library path to give it.

I tried to upgrade to CMake v 3.28 rc2, to be able to use the CURL_USE_STATIC_LIBS hint as documented here https://cmake.org/cmake/help/latest/module/FindCURL.html

I have a bit doubt whether i used the hint correctly - i could not find an example in the documentation. I tried this:

find_package(CURL REQUIRED HINTS CURL_USE_STATIC_LIBS)

The reason i am not sure is that the find_package documentation says that HINTS accepts a directory name as argument, but CURL_USE_STATIC_LIBS does not look like a directory name.

Doing this made no difference. Do i need more changes (specify someting different than CURL::libcurl to target_link_libraries, maybe?)

Can you perhaps message around FindCURL’s creation of the CURL::libcurl target and see what values it is getting for various properties?

I am not very experienced in CMake. What exactly do you want me to message? How do i output the contents of CURL::libcurl

Can you specify the syntax for the massage call?

I would copy the set_target_properties call(s) and change set_target_properties to message. It’ll drop spaces, but it should be good enough to see if things are at least sane.

I did this in cmakedeps_macros.cmake in the build dir (and other places that did not fire):

		      message("Before3: " ${_LIB_NAME} PROPERTIES IMPORTED_IMPLIB${config_suffix} ${CONAN_FOUND_LIBRARY})
              set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION${config_suffix} ${CONAN_FOUND_LIBRARY} IMPORTED_NO_SONAME ${no_soname_mode})

Result:

C:\Users\torsiver\Projects\link_curl\build>cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
-- Using Conan toolchain: C:/Users/torsiver/Projects/link_curl/build/conan_toolchain.cmake
-- Conan toolchain: C++ Standard 14 with extensions OFF
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19044.
-- Conan: Component target declared 'CURL::libcurl'
Before3: CONAN_LIB::libcurl_libcurl_RELEASEPROPERTIESIMPORTED_IMPLIB_RELEASEC:/Users/torsiver/.conan2/p/libcu75d014a1ff3cb/p/lib/libcurl.lib
Before3: CONAN_LIB::libcurl_CURL_libcurl_libcurl_RELEASEPROPERTIESIMPORTED_IMPLIB_RELEASEC:/Users/torsiver/.conan2/p/libcu75d014a1ff3cb/p/lib/libcurl.lib
-- Conan: Component target declared 'OpenSSL::Crypto'
-- Conan: Component target declared 'OpenSSL::SSL'
-- Conan: Target declared 'openssl::openssl'
Before3: CONAN_LIB::openssl_libssl_RELEASEPROPERTIESIMPORTED_IMPLIB_RELEASEC:/Users/torsiver/.conan2/p/opens00e605497815b/p/lib/libssl.lib
Before3: CONAN_LIB::openssl_libcrypto_RELEASEPROPERTIESIMPORTED_IMPLIB_RELEASEC:/Users/torsiver/.conan2/p/opens00e605497815b/p/lib/libcrypto.lib
Before3: CONAN_LIB::openssl_OpenSSL_SSL_libssl_RELEASEPROPERTIESIMPORTED_IMPLIB_RELEASEC:/Users/torsiver/.conan2/p/opens00e605497815b/p/lib/libssl.lib
Before3: CONAN_LIB::openssl_OpenSSL_Crypto_libcrypto_RELEASEPROPERTIESIMPORTED_IMPLIB_RELEASEC:/Users/torsiver/.conan2/p/opens00e605497815b/p/lib/libcrypto.lib
-- Conan: Target declared 'ZLIB::ZLIB'
Before3: CONAN_LIB::zlib_zlib_RELEASEPROPERTIESIMPORTED_IMPLIB_RELEASEC:/Users/torsiver/.conan2/p/zlib462c154a4e854/p/lib/zlib.lib
-- Conan: Including build module from 'C:/Users/torsiver/.conan2/p/opens00e605497815b/p/lib/cmake/conan-official-openssl-variables.cmake'
linkCurlCURL::libcurl
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: C:/Users/torsiver/Projects/link_curl/build

The logging is from the else block of “if(is_host_windows AND library_type STREQUAL “SHARED”)”

This feels like something Conan is not setting up properly rather than CMake’s FindCURL. I’d ask the Conan folks about it, but if something is wrong on CMake’s side, feel free to report back here.

I will try. Thanks for the assistance. Maybe in time i will be able to dig deeper on my own, but i am still a rookie in Conan/CMake